Ineedanswers
Ineedanswers

Reputation: 91

How to capitalize the first letter of a string

I have a string like this

var sentence string = "the biggest ocean is the Pacific ocean"

I want to be able to capitalize the first letter t in the input string, so that the string becomes

"The biggest ocean is the Pacific ocean"

How to do that in Go?

I have tried using strings.Title and strings.ToTitle however they don't do what I want.

Upvotes: 7

Views: 10239

Answers (4)

blackgreen
blackgreen

Reputation: 45041

Assuming that your input string is valid UTF-8, this thread (Golang - ToUpper() on a single byte?) is close enough, though not quite a perfect duplicate. We can build on that to come to an acceptable solution using unicode.ToUpper on the first rune of the string.

Most performant solution

The most performant solution (see benchmarks below) is the one suggested by this answer which uses utf8.DecodeRuneInString although you probably want to use ToUpper and account for possible errors:

r, size := utf8.DecodeRuneInString(text)
if r == utf8.RuneError {
    // handle error
}
s = string(unicode.ToUpper(r)) + text[size:]

Here indexing the string with [] doesn't break the encoding because size is guaranteed to be a valid offset, according to the rune we just decoded.

Other solution

    r := []rune(s)
    r[0] = unicode.ToUpper(r[0])
    s = string(r)

Or with a "clever" one-liner:

    s := string(append([]rune{unicode.ToUpper(r[0])}, r[1:]...))

Unlike strings, rune slices are not immutable, so you can replace the first rune with ToUpper, which will take care of non-ASCII and/or multi-byte code points that do have upper cases (e.g. Russian) and leave alone those that don't (e.g. Asian scripts)

ToUpper vs. ToTitle

There is a difference between UPPER case and TITLE case, which is simply explained here. In short, digraph characters like DŽ will have different title case (Dž, only first grapheme capitalized) and upper cases (DŽ, both graphemes capitalized). If you actually need titlecase, use unicode.ToTitle.

Large input strings

Converting string to/from []rune involves copying, because you get a mutable slice from an immutable string. Do profile your application if you expect to use it in performance-sensitive code.

If you have a sizeable input string where a full rune slice conversion becomes too expensive, you can work around this using a capped strings.SplitN on some separator — or strings.Cut since later Go versions — to extract the first word of the text and use only that in the conversion:

sep := " "
ss := strings.SplitN(s, sep, 2)

r := []rune(ss[0])
r[0] = unicode.ToUpper(r[0])

s = string(r) + sep + ss[1])

Benchmarks

Benchmarking with a ~30K input string shows a significant difference, although the best and the second best differ by a small margin (benchmark updated with Go 1.22):

go test -v -bench=. -benchmem
goos: darwin
goarch: arm64
pkg: example.com
BenchmarkRuneConv-10            6730        168665 ns/op      155648 B/op          2 allocs/op
BenchmarkSplitN-10            504634          2357 ns/op       32800 B/op          2 allocs/op
BenchmarkDecodeRune-10        533928          2307 ns/op       32768 B/op          1 allocs/op
PASS
ok      example.com 4.981s

With smaller strings, the SplitN/Cut solution isn't necessary and utf8.DecodeRuneInString is the clear winner.

A playground: https://go.dev/play/p/HpCBM7cRflZ

Upvotes: 9

Ashutosh Singh
Ashutosh Singh

Reputation: 1082

The simplest way to achieve the desired result is to use strings.ToUpper() function. Refer

    var input string = "the biggest ocean is the Pacific ocean"
    res := strings.ToUpper(input[:1]) + input[1:]

    fmt.Println(res)

OR

You can try it on goplayground

Upvotes: 3

Gastro Health
Gastro Health

Reputation: 7

Get the first rune, title case that rune and reassemble the string:

sentence := "the biggest ocean is the Pacific ocean"
r, i := utf8.DecodeRuneInString(sentence)
sentence = string(unicode.ToTitle(r)) + sentence[i:]
fmt.Println(sentence)

Upvotes: -1

CleanMachine1
CleanMachine1

Reputation: 48

I have simple solution for you.

Its a fork I have of someones project on Github

https://github.com/CleanMachine1/capitalise

To use it just run in a terminal:

go mod init MODULENAME
go get github.com/cleanmachine1/capitalise

then in your code you can use


package main

import ("github.com/cleanmachine1/capitalise")

func main(){
 sentence = capitalise.First(sentence)
}

Upvotes: -13

Related Questions