There is also strings.Fields but it’s defined as:

func Fields(s string) []string {

return FieldsFunc(s, unicode.IsSpace)

}

so all the hard work is done in FieldsFunc anyway.

Split is also facade to different function:

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

return genSplit(s, sep, 0, -1)

}

but since getSplit it not exported let’s focus on how Split works (which is defined by passing specific configuration through 3rd and 4h parameter).

Both functions work in pretty much the same way. Input string is traversed twice — first to see how many chunks have been found and allocate memory for resulting slice. Second pass just finds the same chunks but also saves them. Where is the difference then?

Split assumes that blank (space before first character) belongs to the first matching chunk. If then separator matches input’s prefix we’ll get blank as first element in the resulting slice. The same when it goes to end of string — if separator matches postfix then blank will be one of resulted parts:

fmt.Printf(“%#v

”, strings.Split(“/a/b/c”, “/”)) // []string{"", "a", "b", "c"}

fmt.Printf(“%#v

”, strings.Split(“a/b/c/”, “/”)) // []string{"a", "b", "c", ""}

FieldsFunc has slightly different logic — start and end of input are treated conversely. Also it merges contiguous separator characters into single separator space:

fmt.Printf(“%#v

”, strings.FieldsFunc(“a//b”, func(c rune) bool { return c == ‘/’ })) // []string{"a", "b"}

fmt.Printf(“%#v

”, strings.Split(“a//b”, “/”)) // []string{"a", "", "b"}

See “How to crash strings.FieldsFunc in Go” for more information about FieldsFunc.