The Go standard library strings
package has a Join
function:
func Join(elems []string, sep string) string
Your function is a simple extension of strings.Join
:
func JoinLast(elems []string, sep, lastSep string) string
However, for no obvious reason, you chose a different function parameter signature:
func JoinLast(sep string, lastSep string, words ...string) string
We need a comment to explain why this isn't an arbitrary or idiosyncratic decision.
Your testing is inadequate. Check boundary conditions. Your function fails on an empty words
list.
words = []string{}
You have not provided any testing
benchmarks. For example,
BenchmarkJoin-4 5534918 207.9 ns/op 104 B/op 5 allocs/op
func JoinStringsIntoArray(sep string, lastSep string, words ...string) string { lastElementIndex := len(words) - 1 var joinedString string for index, word := range words[0:lastElementIndex] { if index == lastElementIndex-1 { sep = lastSep } joinedString += word + sep } joinedString += words[lastElementIndex] return joinedString } func BenchmarkJoin(b *testing.B) { words := []string{"one", "two", "three", "four", "five"} b.ReportAllocs() b.ResetTimer() for N := 0; N < b.N; N++ { JoinStringsIntoArray(", ", " and ", words...) } }
You can do better. For example, minimize allocation,
BenchmarkJoin-4 16612879 70.95 ns/op 32 B/op 1 allocs/op
func JoinLast(elems []string, sep, lastSep string) string { var join strings.Builder joinCap := 0 for i := 0; i < len(elems); i++ { joinCap += len(elems[i]) } if len(elems) > 1 { joinCap += len(lastSep) if len(elems) > 2 { joinCap += (len(elems) - 2) * len(sep) } } join.Grow(joinCap) last := len(elems) - 1 - 1 for i, elem := range elems { if i >= last { if i == last { sep = lastSep } else { sep = "" } } join.WriteString(elem) join.WriteString(sep) } return join.String() } func BenchmarkJoin(b *testing.B) { words := []string{"one", "two", "three", "four", "five"} b.ReportAllocs() b.ResetTimer() for N := 0; N < b.N; N++ { JoinLast(words, ", ", " and ") } }