Go strings Package

Search, split, replace, trim, and transform strings — all the functions you'll actually reach for.

Contains Split / Join Replace Trim HasPrefix / HasSuffix Index ToUpper / ToLower Cut
🔍

Searching

Contains — check if a substring exists Contains
strings.Contains("gopher", "ph")       // true
strings.Contains("gopher", "xyz")      // false
strings.Contains("gopher", "")         // true — empty is always contained

// ContainsAny — true if any character in the set is present
strings.ContainsAny("hello", "aeiou")  // true — contains 'e' and 'o'
strings.ContainsAny("rhythm", "aeiou") // false — no vowels

// ContainsRune — check for a specific Unicode code point
strings.ContainsRune("hello", 'o')     // true
HasPrefix & HasSuffix Prefix / Suffix
strings.HasPrefix("Gopher", "Go")      // true
strings.HasPrefix("Gopher", "go")      // false — case-sensitive

strings.HasSuffix("Amigo", "go")       // true
strings.HasSuffix("image.png", ".png") // true — handy for file extensions
Index — find position of a substring Index
// Returns byte index of first match, or -1
strings.Index("chicken", "ken")        // 4
strings.Index("chicken", "xyz")        // -1

// LastIndex — find last occurrence
strings.LastIndex("go gopher go", "go") // 10

// IndexAny — first position of any character in the set
strings.IndexAny("chicken", "aeiou")    // 2 — 'i'

// Count — non-overlapping occurrences
strings.Count("cheese", "e")            // 3
strings.Count("five", "")               // 5 — empty counts rune boundaries
✂️

Split & Join

Split — slice a string by separator Split
// Split — all parts, separator removed
strings.Split("a,b,c", ",")            // ["a" "b" "c"]
strings.Split("hello", "")             // ["h" "e" "l" "l" "o"] — split each char

// SplitN — limit number of parts (last part holds remainder)
strings.SplitN("a,b,c,d", ",", 2)      // ["a" "b,c,d"]
strings.SplitN("a,b,c,d", ",", 3)      // ["a" "b" "c,d"]

// SplitAfter — keep the separator on the left piece
strings.SplitAfter("a,b,c", ",")       // ["a," "b," "c"]

// Fields — split on any whitespace, trims leading/trailing
strings.Fields("  foo bar  baz  ")     // ["foo" "bar" "baz"]
Join — combine a slice into one string Join
parts := []string{"hello", "world", "go"}

strings.Join(parts, ", ")              // "hello, world, go"
strings.Join(parts, " ")               // "hello world go"
strings.Join(parts, "")                // "helloworldgo"

// Common pattern: split then process then rejoin
words := strings.Split("one two three", " ")
result := strings.Join(words, "-")    // "one-two-three"
🔄

Replace & Transform

Replace & ReplaceAll Replace
// Replace(s, old, new, n) — replace first n
strings.Replace("oink oink oink", "oink", "moo", 2)
// "moo moo oink"

// n = -1 replaces all (same as ReplaceAll)
strings.Replace("oink oink oink", "oink", "moo", -1)
// "moo moo moo"

strings.ReplaceAll("foo foo foo", "foo", "bar")
// "bar bar bar"
Case & Repeat Transform
strings.ToUpper("Gopher")    // "GOPHER"
strings.ToLower("Gopher")    // "gopher"
strings.Title("hello world") // "Hello World"

strings.Repeat("na", 4)       // "nananana"
strings.Repeat("-", 20)       // "--------------------"
Map — transform every rune Map
// Map applies a function to every rune in the string
rot13 := func(r rune) rune {
    switch {
    case r >= 'A' && r <= 'Z':
        return 'A' + (r-'A'+13)%26
    case r >= 'a' && r <= 'z':
        return 'a' + (r-'a'+13)%26
    }
    return r
}
strings.Map(rot13, "Hello, Gopher!")   // "Uryyb, Tbcure!"

// Drop all digits
noDigits := func(r rune) rune {
    if r >= '0' && r <= '9' { return -1 } // -1 drops the rune
    return r
}
strings.Map(noDigits, "a1b2c3")          // "abc"
✂️

Trim

💡
Trim, TrimLeft, and TrimRight remove any characters in the cutset, not the cutset string itself. Use TrimPrefix / TrimSuffix when you want to remove an exact string.
Trim by character set Trim
// Trim — remove cutset chars from both ends
strings.Trim("¡¡¡Hello!!!", "!¡")          // "Hello"

// TrimLeft / TrimRight — one side only
strings.TrimLeft("¡¡¡Hello!!!", "!¡")      // "Hello!!!"
strings.TrimRight("¡¡¡Hello!!!", "!¡")     // "¡¡¡Hello"

// TrimSpace — removes all leading/trailing whitespace
strings.TrimSpace("  \t Hello, Go \n  ")   // "Hello, Go"
TrimPrefix & TrimSuffix — remove exact strings Prefix / Suffix
// Only removes the prefix/suffix if it matches exactly; no-op otherwise
strings.TrimPrefix("Goodbye, world!", "Goodbye, ") // "world!"
strings.TrimPrefix("Hello, world!", "Goodbye, ")  // "Hello, world!" — no match, unchanged

strings.TrimSuffix("image.png", ".png")             // "image"
strings.TrimSuffix("image.jpg", ".png")             // "image.jpg" — no match

// TrimFunc — trim using a custom predicate
strings.TrimFunc("  123abc456  ", unicode.IsSpace)  // "123abc456"
🪓

Cut

ℹ️
Cut was added in Go 1.18. It's cleaner than Index + manual slicing when you want to split a string on the first occurrence of a separator.
Cut — split on first separator Go 1.18+
// Cut(s, sep) → before, after, found
before, after, found := strings.Cut("user@example.com", "@")
// before="user"  after="example.com"  found=true

before, after, found = strings.Cut("no-at-sign", "@")
// before="no-at-sign"  after=""  found=false

// Parsing key=value pairs
for _, pair := range []string{"host=localhost", "port=5432"} {
    key, val, _ := strings.Cut(pair, "=")
    fmt.Printf("%s → %s\n", key, val)
}
// host → localhost
// port → 5432
CutPrefix Go 1.20+
// CutPrefix(s, prefix) → after, found
after, found := strings.CutPrefix(
    "https://example.com", "https://")
// after="example.com"  found=true

after, found = strings.CutPrefix(
    "http://example.com", "https://")
// after="http://example.com"  found=false
CutSuffix Go 1.20+
// CutSuffix(s, suffix) → before, found
before, found := strings.CutSuffix(
    "archive.tar.gz", ".gz")
// before="archive.tar"  found=true

before, found = strings.CutSuffix(
    "archive.tar.gz", ".zip")
// before="archive.tar.gz"  found=false
🏗️

Building Strings

⚠️
Don't concatenate strings in a loop with += — each iteration allocates a new string. Use strings.Builder for efficient incremental construction.
strings.Builder — zero-allocation building Builder
var b strings.Builder

for i := 0; i < 5; i++ {
    fmt.Fprintf(&b, "item%d ", i)
}
fmt.Println(b.String()) // "item0 item1 item2 item3 item4 "

// Other write methods
b.Reset()
b.WriteString("Hello")
b.WriteByte(',')
b.WriteRune(' ')
b.WriteString("World")
fmt.Println(b.String()) // "Hello, World"
fmt.Println(b.Len())    // 12
⚖️

Compare & Misc

Comparison functions Compare
// Compare — lexicographic: returns -1, 0, or 1
strings.Compare("apple", "banana")  // -1  (apple < banana)
strings.Compare("banana", "apple")  // 1
strings.Compare("apple", "apple")   // 0

// EqualFold — case-insensitive equality (handles Unicode)
strings.EqualFold("Go", "go")       // true
strings.EqualFold("HELLO", "hello") // true
strings.EqualFold("Go", "Java")     // false

// Clone — explicit copy (avoids retaining a large backing array)
s := strings.Clone("hello")         // new allocation, same content
📋

Quick Reference

Function Returns Description
Contains(s, substr)boolReports whether substr is within s
ContainsAny(s, chars)boolTrue if any char in set is in s
ContainsRune(s, r)boolTrue if rune r is in s
HasPrefix(s, prefix)boolTrue if s starts with prefix
HasSuffix(s, suffix)boolTrue if s ends with suffix
Index(s, substr)intByte index of first match, or -1
LastIndex(s, substr)intByte index of last match, or -1
IndexAny(s, chars)intFirst position of any char in set
Count(s, substr)intNon-overlapping occurrences of substr
Split(s, sep)[]stringSlice split by sep
SplitN(s, sep, n)[]stringSplit into at most n parts
SplitAfter(s, sep)[]stringSplit, keeping sep on left piece
Fields(s)[]stringSplit on whitespace, trims ends
Join(elems, sep)stringConcatenate slice with separator
Replace(s, old, new, n)stringReplace first n occurrences
ReplaceAll(s, old, new)stringReplace all occurrences
ToUpper(s)stringAll letters to uppercase
ToLower(s)stringAll letters to lowercase
Title(s)stringFirst letter of each word uppercased
Repeat(s, n)strings repeated n times
Map(f, s)stringApply function to every rune
Trim(s, cutset)stringRemove cutset chars from both ends
TrimLeft(s, cutset)stringRemove cutset chars from left only
TrimRight(s, cutset)stringRemove cutset chars from right only
TrimSpace(s)stringRemove leading/trailing whitespace
TrimPrefix(s, prefix)stringRemove exact prefix string
TrimSuffix(s, suffix)stringRemove exact suffix string
TrimFunc(s, f)stringTrim using a custom rune predicate
Cut(s, sep)before, after, foundSplit on first sep (Go 1.18+)
CutPrefix(s, prefix)after, foundRemove prefix, report if found (Go 1.20+)
CutSuffix(s, suffix)before, foundRemove suffix, report if found (Go 1.20+)
Compare(a, b)intLexicographic compare: -1, 0, 1
EqualFold(s, t)boolCase-insensitive equality (Unicode)
Clone(s)stringReturns a fresh copy of s