strings, strconv and strings.Builder in Go
Everyday string work in Go with the strings package, convert between strings and numbers with strconv, and build strings efficiently with strings.Builder.
Splitting input, trimming spaces, turning "42" into a number and building output are things you do every day. Go keeps these in three places: strings for searching and changing text, strconv for number conversions, and strings.Builder for building text in a loop.
The strings Functions You Will Use Most
package main
import (
"fmt"
"strings"
)
func main() {
line := " name=Asha; role=admin; team=docs "
clean := strings.TrimSpace(line)
fmt.Printf("%q\n", clean)
for _, part := range strings.Split(clean, "; ") {
key, value, ok := strings.Cut(part, "=")
if ok {
fmt.Println(key, "->", value)
}
}
fmt.Println(strings.Contains(clean, "admin"))
fmt.Println(strings.HasPrefix(clean, "name="))
fmt.Println(strings.ToUpper("go"), strings.Repeat("-", 5))
fmt.Println(strings.ReplaceAll("a.b.c", ".", "/"))
fmt.Println(strings.Fields(" split on any space "))
fmt.Println(strings.Join([]string{"go", "rust", "tauri"}, ", "))
fmt.Println(strings.EqualFold("Go", "GO"))
}
"name=Asha; role=admin; team=docs"
name -> Asha
role -> admin
team -> docs
true
true
GO -----
a/b/c
[split on any space]
go, rust, tauri
true
strings.Cut splits around the first match and tells you if it was found, which is cleaner than Split plus checking the length. strings.Fields splits on any run of whitespace, so it is better than Split(s, " ") for user input. EqualFold compares without caring about case.
Split on an empty string:
strings.Split("", ",") returns [""], a slice with one empty string, not an empty slice. Check for empty input before splitting, or you will process a blank item.
Strings and Numbers with strconv
strconv converts in both directions, and parsing returns an error you must check:
package main
import (
"fmt"
"strconv"
)
func main() {
n, err := strconv.Atoi("42")
fmt.Println(n+1, err)
_, err = strconv.Atoi("42a")
fmt.Println(err)
big, _ := strconv.ParseInt("9000000000", 10, 64)
f, _ := strconv.ParseFloat("3.75", 64)
b, _ := strconv.ParseBool("true")
fmt.Println(big, f, b)
fmt.Println(strconv.Itoa(2026) + " docs")
fmt.Println(strconv.FormatFloat(3.14159, 'f', 2, 64))
fmt.Println(strconv.Quote("say \"hi\""))
}
43 <nil>
strconv.Atoi: parsing "42a": invalid syntax
9000000000 3.75 true
2026 docs
3.14
"say \"hi\""
Atoi is short for "ASCII to integer" and returns an int. ParseInt(s, 10, 64) lets you pick the base and size, and reports value out of range when the number is too big.
string(n) does not give you digits:
Converting an integer with string(n) gives the character with that code, so string(rune(65)) is "A". go vet warns about string(int) for this reason. Use strconv.Itoa(65) or fmt.Sprint(65) to get "65".
Building Strings with strings.Builder
Go strings cannot be changed. Every s += "x" creates a new string and copies the old one, so doing it in a big loop gets slow. strings.Builder appends into one growing buffer:
package main
import (
"fmt"
"strings"
)
func main() {
rows := [][]string{{"id", "name"}, {"1", "Asha"}, {"2", "Ravi"}}
var b strings.Builder
for _, row := range rows {
b.WriteString(strings.Join(row, ","))
b.WriteByte('\n')
}
fmt.Fprintf(&b, "total rows: %d\n", len(rows)-1)
fmt.Print(b.String())
}
id,name
1,Asha
2,Ravi
total rows: 2
The zero value is ready to use, so var b strings.Builder is all you need. It is an io.Writer, so fmt.Fprintf(&b, ...) writes into it. Call b.Grow(n) first if you know roughly how big the result will be.
For a handful of pieces, + or fmt.Sprintf is fine and easier to read. Use a Builder when you build a string in a loop.
Bytes, runes and len:
len("héllo") is 6, because len counts bytes and é takes two bytes in UTF-8. Use utf8.RuneCountInString for the number of characters, and loop with for _, r := range s to get runes instead of bytes.
Text handling covered:
If you reach for strings.Cut and Fields to parse input, strconv with an error check to read numbers, and strings.Builder in loops, you have the everyday text tools in place.
Summary
Use the strings package for trimming, splitting, searching and replacing, with Cut and Fields as the most useful helpers for parsing. Convert numbers with strconv.Atoi, ParseInt, ParseFloat and Itoa, always checking parse errors, and never with string(n). Build text in loops with strings.Builder instead of +=.