How to concatenate strings efficiently in Go

Daryl Ng
2 min readFeb 6, 2021

Have you ever wonder if you are concatenating strings efficiently? I did, and so here are the results.

But first, let’s discuss on three ways to concatenate strings.

1. Concatenation using +

The easiest and cleanest way to concatenate strings is to use + .

foobar := "foo" + "bar"

2. Concatenation using strings.Builder

Another way is with strings.Builder . As compared to the first method, this method is much longer and code readability might be affected.

var sb strings.Builder
sb.WriteString("foo")
sb.WriteString("bar")
// sb.String()

3. Concatenation using bytes.Buffer

Last method is with bytes.Buffer . Similar to the second method, it requires at least three lines of code.

var bb bytes.Buffer
bb.WriteString("foo")
bb.WriteString("bar")
// bb.String()

Create the functions

Now let’s create three functions that concatenate strings using the three methods above.

func StringConcatWithAdd() string {
var s string
for i := 0; i < 100; i++ {
s = s + "x"
}

return s
}

func StringConcatWithStringsBuilder() string {
var sb strings.Builder
for i := 0; i < 100; i++ {
sb.WriteString("x")
}

return sb.String()
}

func StringConcatWithBytesBuffer() string {
var bb bytes.Buffer
for i := 0; i < 100; i++ {
bb.WriteString("x")
}

return bb.String()
}

Preparing for the benchmark

I am using the testing package in Go to benchmark the above functions.

func BenchmarkStringConcatWithAdd(b *testing.B) {
b.ReportAllocs()

for i := 0; i < b.N; i++ {
strconcat.StringConcatWithAdd()
}
}

func BenchmarkStringConcatWithStringsBuilder(b *testing.B) {
b.ReportAllocs()

for i := 0; i < b.N; i++ {
strconcat.StringConcatWithStringsBuilder()
}
}

func BenchmarkStringConcatWithBytesBuffer(b *testing.B) {
b.ReportAllocs()

for i := 0; i < b.N; i++ {
strconcat.StringConcatWithBytesBuffer()
}
}

The results

BenchmarkStringConcatWithAdd
BenchmarkStringConcatWithAdd-8 252232 4709 ns/op 5728 B/op 99 allocs/op
BenchmarkStringConcatWithStringsBuilder
BenchmarkStringConcatWithStringsBuilder-8 3282949 363 ns/op 248 B/op 5 allocs/op
BenchmarkStringConcatWithBytesBuffer
BenchmarkStringConcatWithBytesBuffer-8 1545480 825 ns/op 320 B/op 3 allocs/op

Surprisingly (or maybe not), the easiest way is not the best or most efficient method. Since strings in Go are immutable, the above example resulted in 99 allocs/op!

strings.Builder has the best performance and those minor improvement can add up when you have lots of concatenations.

Conclusion

Let’s be honest, strings.Builder has the best performance, but the above example is naive and it is to illustrate the difference between the methods. We wouldn’t be concatenating strings with a for loop. Most of the time we are doing things like this url := Host + "/path" . But if you are doing so, you should consider using strings.Builder instead.

Performance improvements should not be your biggest priority at the start. Benchmark your code to find performance issues before tweaking anything. Trivial concatenation will not benefit much from these changes.

Hope you find this beneficial! Do give it a clap or share it if you think so.

Do follow me if you have not already done so!

--

--