Skip to content

strings

The strings package implements simple functions to operate on UTF-8 encoded strings. Simply put, it is a toolkit for operating on strings.

Official documentation: strings package - strings - Go Packages

TIP

Go natively supports UTF8 characters, and all string operations are based on UTF8.

Import

go
import (
   "strings"
)

The following will explain commonly used functions with examples.

Clone String

go
func Clone(s string) string

Allocates a new memory for the copied replica. If an empty string is passed, no memory is allocated and an empty string is returned.

go
func TestClone(t *testing.T) {
   ori := "hello 世界"
   copys := strings.Clone(ori)
   fmt.Println(ori, copys)
   fmt.Println(&ori, &copys)
}
=== RUN   TestClone
hello 世界 hello 世界
0xc00005e5d0 0xc00005e5e0
--- PASS: TestClone (0.00s)
PASS

Compare Strings

go
func Compare(a, b string) int

Compares strings a and b lexicographically. If a > b, returns 1; if a < b, returns -1; if a = b, returns 0.

go
func TestCompare(t *testing.T) {
  fmt.Println(strings.Compare("abc", "abe"))
  fmt.Println(strings.Compare("abcd", "abe"))
  fmt.Println(strings.Compare("abijk", "abe"))
  fmt.Println(strings.Compare("abe", "abe"))
}
=== RUN   TestCompare
-1
-1
1
0
--- PASS: TestCompare (0.00s)
PASS

Contains String

go
func Contains(s, substr string) bool

Determines whether string s contains substring substr.

go
func TestContains(t *testing.T) {
  fmt.Println(strings.Contains("abcdefg", "a"))
  fmt.Println(strings.Contains("abcdefg", "abc"))
  fmt.Println(strings.Contains("abcdefg", "ba"))
}
=== RUN   TestContains
true
true
false
--- PASS: TestContains (0.00s)
PASS
go
func ContainsAny(s, chars string) bool

Determines whether any character's Unicode code point in string chars is within string s. In other words, whether s contains any character from chars.

go
func TestContainsAny(t *testing.T) {
  fmt.Println(strings.ContainsAny("abcedfg", "bac"))
  fmt.Println(strings.ContainsAny("abcedfg", "gfdecba"))
}
=== RUN   TestContainsAny
true
--- PASS: TestContainsAny (0.00s)
PASS
go
func ContainsRune(s string, r rune) bool

Determines whether string s contains rune r.

go
func TestContainsRune(t *testing.T) {
   fmt.Println(strings.ContainsRune("abcedf", 'a'))
   fmt.Println(strings.ContainsRune("abcedf", 'b'))
   fmt.Println(strings.ContainsRune("你好世界", ''))
}
=== RUN   TestContainsRune
true
true
true
--- PASS: TestContainsRune (0.00s)
PASS

Count Substring Occurrences

go
func Count(s, substr string) int

Returns the number of times substring substr appears in string s.

go
func TestCount(t *testing.T) {
  fmt.Println(strings.Count("3.1415926", "1"))
  fmt.Println(strings.Count("there is a girl", "e"))
  fmt.Println(strings.Count("there is a girl", ""))
}
=== RUN   TestCount
2
2
16
--- PASS: TestCount (0.00s)
PASS

Cut String

go
func Cut(s, sep string) (before, after string, found bool)

Cuts the first occurrence of substring sep in s and returns the result after cutting.

  • before - The string before the cut substring position
  • after - The string after the cut substring position
  • found - Whether the substring was found
go
func TestCut(t *testing.T) {
  show := func(s, sep string) {
    before, after, found := strings.Cut(s, sep)
    fmt.Printf("Cut(%q, %q) = %q, %q, %v\n", s, sep, before, after, found)
  }
  show("Hello world", " ")
  show("Hello world", "world")
  show("Hello world", "Hello")
  show("Hello world", "Hello world")
}
=== RUN   TestCut
Cut("Hello world", " ") = "Hello", "world", true
Cut("Hello world", "world") = "Hello ", "", true
Cut("Hello world", "Hello") = "", " world", true
Cut("Hello world", "Hello world") = "", "", true
--- PASS: TestCut (0.00s)
PASS

Case-Insensitive Equality

go
func EqualFold(s, t string) bool

Returns whether strings s and t are equal ignoring case.

go
func TestEqualFold(t *testing.T) {
   fmt.Println(strings.EqualFold("你好", "你好"))
   fmt.Println(strings.EqualFold("Hello", "Hello"))
   fmt.Println(strings.EqualFold("Hello", "hELLO"))
}
=== RUN   TestEqualFold
true
true
true
--- PASS: TestEqualFold (0.00s)
PASS

Split String

go
func Fields(s string) []string
go
func FieldsFunc(s string, f func(rune) bool) []string

The former splits the string by whitespace, while the latter uses the return value of function f to decide whether to split the string.

go
func TestField(t *testing.T) {
   fmt.Printf("%q\n", strings.Fields(" a b c d e f g "))
   fmt.Printf("%q\n", strings.FieldsFunc("a,b,c,d,e,f,g", func(r rune) bool {
      return r == ','
   }))
}
=== RUN   TestField
["a" "b" "c" "d" "e" "f" "g"]
["a" "b" "c" "d" "e" "f" "g"]
--- PASS: TestField (0.00s)
PASS

Find Prefix/Suffix

go
func HasPrefix(s, prefix string) bool
go
func HasSuffix(s, suffix string) bool

The former searches for a prefix, and the latter searches for a suffix. If interested, you can check the source code implementation here, which is quite clever.

go
func TestPreSuffix(t *testing.T) {
   str := "abbc cbba"
   fmt.Println(strings.HasPrefix(str, "abb"))
   fmt.Println(strings.HasSuffix(str, "bba"))
}
=== RUN   TestPreSuffix
true
true
--- PASS: TestPreSuffix (0.00s)
PASS

Substring Position

Returns the index of the first occurrence of a substring:

go
func Index(s, substr string) int

Returns the index of the first occurrence of any character from the substring:

go
func IndexAny(s, chars string) int

Returns the index of the first occurrence of a rune:

go
func IndexRune(s string, r rune) int

Example:

go
func TestIndex(t *testing.T) {
   fmt.Println(strings.Index("abcdefg", "bc"))
   fmt.Println(strings.IndexAny("abcdefg", "cb"))
   fmt.Println(strings.IndexRune("abcdefg", 'g'))
}
=== RUN   TestIndex
1
1
6
--- PASS: TestIndex (0.00s)
PASS

Returns the index of the last occurrence of a substring:

go
func LastIndex(s, substr string) int

Returns the index of the last occurrence of any character from the substring:

go
func LastIndexAny(s, chars string) int

Example:

go
func TestLastIndex(t *testing.T) {
  fmt.Println(strings.LastIndex("abcdefga", "a"))
  fmt.Println(strings.LastIndexAny("abcdefghisa", "ba"))
}

Map and Replace String

Map returns a copy of string s with all its characters modified according to the mapping function. If the mapping returns a negative value, the character is deleted from the string without replacement.

go
func Map(mapping func(rune) rune, s string) string

Example:

go
func TestMap(t *testing.T) {
   fmt.Println(strings.Map(func(r rune) rune {
      return r - 32
   }, "abcdefghijk"))
   fmt.Println(strings.Map(func(r rune) rune {
      return r + 32
   }, "ABCDEFGHIJK"))
   fmt.Println(strings.Map(func(r rune) rune {
      if r < 'F' {
         return -1
      } else {
         return r
      }
   }, "ABCDEFGHIJK"))
}

Output:

text
=== RUN   TestMap
ABCDEFGHIJK
abcdefghijk
FGHIJK
--- PASS: TestMap (0.00s)
PASS

Repeat String

Replicates the string according to the given count. If negative, it will cause a panic.

go
func Repeat(s string, count int) string

Example:

go
func TestRepeat(t *testing.T) {
   fmt.Println(strings.Repeat("a", 10))
   fmt.Println(strings.Repeat("abc", 10))
}

Output:

=== RUN   TestRepeat
aaaaaaaaaa
abcabcabcabcabcabcabcabcabcabc
--- PASS: TestRepeat (0.00s)
PASS

Replace String

s is the source string, old refers to the part to be replaced, new refers to the replacement part for old, and n refers to the number of replacements. When n is less than 0, it means unlimited replacements.

go
func Replace(s, old, new string, n int) string

Example:

go
func TestReplace(t *testing.T) {
   fmt.Println(strings.Replace("Hello this is golang", "golang", "c++", 1))
   fmt.Println(strings.Replace("Hello this is golang", "o", "c", -1))
   fmt.Println(strings.Replace("Hello this is golang", "o", "c", 1))
}

Output:

=== RUN   TestReplace
Hello this is c++
Hellc this is gclang
Hellc this is golang
--- PASS: TestReplace (0.00s)
PASS

Convenience function for Replace, equivalent to strings.Replace(s, old, new, -1):

go
func ReplaceAll(s, old, new string) string

Example:

go
func TestReplaceAll(t *testing.T) {
  fmt.Println(strings.ReplaceAll("Hello this is golang", "o", "c++"))
}

Output:

=== RUN   TestReplaceAll
Hellc++ this is gc++lang
--- PASS: TestReplaceAll (0.00s)
PASS

Split String

Splits string s into a string slice according to substring sep:

go
func Split(s, sep string) []string

Splits string s into a string slice according to substring sep, with the number of splits determined by n:

go
func SplitN(s, sep string, n int) []string

Splits string s into a string slice containing sep as string elements:

go
func SplitAfter(s, sep string) []string

Splits string s into a string slice containing sep as string elements, with the number of splits determined by n:

go
func SplitAfterN(s, sep string, n int) []string

Example:

go
func TestSplit(t *testing.T) {
   fmt.Printf("%q\n", strings.Split("this is go language", " "))
   fmt.Printf("%q\n", strings.SplitN("this is go language", " ", 2))
   fmt.Printf("%q\n", strings.SplitAfter("this is go language", " "))
   fmt.Printf("%q\n", strings.SplitAfterN("this is go language", " ", 2))
}

Output:

=== RUN   TestSplit
["this" "is" "go" "language"]
["this" "is go language"]
["this " "is " "go " "language"]
["this " "is go language"]
--- PASS: TestSplit (0.00s)
PASS

Case Conversion

Converts English string to lowercase:

go
func ToLower(s string) string

Converts to lowercase string according to the corresponding language's unicode.SpecialCase:

go
func ToLowerSpecial(c unicode.SpecialCase, s string) string

Converts English string to uppercase:

go
func ToUpper(s string) string

Converts to uppercase string according to the corresponding language's unicode.SpecialCase:

go
func ToUpperSpecial(c unicode.SpecialCase, s string) string

Example:

go
func TestLowerAndUpper(t *testing.T) {
   fmt.Println(strings.ToLower("My name is jack,Nice to meet you!"))
   fmt.Println(strings.ToLowerSpecial(unicode.TurkishCase, "Önnek İş"))
   fmt.Println(strings.ToUpper("My name is jack,Nice to meet you!"))
   fmt.Println(strings.ToUpperSpecial(unicode.TurkishCase, "örnek iş"))
}

Output:

=== RUN   TestLowerAndUpper
my name is jack,nice to meet you!
önnek iş
MY NAME IS JACK,NICE TO MEET YOU!
ÖRNEK İŞ
--- PASS: TestLowerAndUpper (0.00s)
PASS

Trim String

Trims both ends of the string, removing any matching characters from cutset:

go
func Trim(s, cutset string) string

Trims the left end of the string, removing any matching characters from cutset:

go
func TrimLeft(s, cutset string) string

Trims the left prefix of the string, removing matching characters from cutset. If not matching, returns string s:

go
func TrimPrefix(s, suffix string) string

Trims the right end of the string, removing any matching characters from cutset:

go
func TrimRight(s, cutset string) string

Trims the right suffix of the string, removing matching characters from cutset. If not matching, returns string s:

go
func TrimSuffix(s, suffix string) string

Example:

go
func TestTrim(t *testing.T) {
  fmt.Println(strings.Trim("!!this is a test statement!!", "!!!"))
  fmt.Println(strings.TrimLeft("!!this is a test statement!!", "!!!"))
  fmt.Println(strings.TrimRight("!!this is a test statement!!", "!!!"))
  fmt.Println(strings.TrimPrefix("!!this is a test statement!!", "!!!"))
  fmt.Println(strings.TrimSuffix("!!this is a test statement!!", "!!!"))
}

Output:

=== RUN   TestTrim
this is a test statement
this is a test statement!!
!!this is a test statement
!!this is a test statement!!
!!this is a test statement!!
--- PASS: TestTrim (0.00s)
PASS

String Builder

String Builder is more memory-efficient than directly manipulating strings.

go
type Builder struct {
  // Internal fields are not exposed
}

Example:

go
func TestBuilder(t *testing.T) {
   builder := strings.Builder{}
   builder.WriteString("hello")
   builder.WriteString(" world")
   fmt.Println(builder.Len())
   fmt.Println(builder.String())
}

Output:

=== RUN   TestBuilder
11
hello world
--- PASS: TestBuilder (0.00s)
PASS

TIP

Do not attempt to pass Builder as a value, for example, when passing strings.Builder as a function parameter, the program will panic:

strings: illegal use of non-zero Builder copied by value

Internally, it has the following code:

go
type Builder struct {
  addr *Builder // Address of itself
  buf  []byte
}

func (b *Builder) copyCheck() {
   if b.addr == nil {
      b.addr = (*Builder)(noescape(unsafe.Pointer(b)))
   } else if b.addr != b {
      panic("strings: illegal use of non-zero Builder copied by value")
   }
}

When copying a Builder by value, the pointer of the internal slice is also copied. Both Builders operate on the same slice when writing strings, which is why value copying is not allowed.

String Replacer

Replacer is used to replace strings:

go
func NewReplacer(oldnew ...string) *Replacer

Example:

go
func TestReplacer(t *testing.T) {
  r := strings.NewReplacer("<", "<", ">", ">")
  fmt.Println(r.Replace("This is <b>HTML</b>!"))
}

Output:

This is <b>HTML</b>!

String Reader

Reader implements io.Reader, io.ReaderAt, io.ByteReader, io.ByteScanner, io.RuneReader, io.RuneScanner, io.Seeker, and io.WriterTo interfaces.

go
func NewReader(s string) *Reader

Example:

go
func TestReader(t *testing.T) {
   reader := strings.NewReader("abcdefghijk")
   buffer := make([]byte, 20, 20)
   read, err := reader.Read(buffer)
   if err != nil {
      log.Panic(err)
   }
   fmt.Println(read)
   fmt.Println(string(buffer))
}

Output:

=== RUN   TestReader
11
abcdefghijk
--- PASS: TestReader (0.00s)
PASS

Golang by www.golangdev.cn edit