Go Programming
String Concatenation
Coding Efficiency
Programming Tips
Go Language Techniques

How to efficiently concatenate strings in go

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

String concatenation in Go is easy to write but not always cheap to execute. The efficient choice depends on how many pieces you are joining, whether you already have a slice of strings, and whether the work happens inside a hot loop.

Use + for Small, Fixed Numbers of Strings

For a few known pieces, the + operator is perfectly fine and usually the clearest option.

go
1package main
2
3import "fmt"
4
5func main() {
6    first := "Hello"
7    second := "Go"
8    message := first + ", " + second + "!"
9    fmt.Println(message)
10}

Do not over-engineer simple cases. The compiler can optimize many straightforward concatenations well.

Use strings.Builder for Repeated Appends

When building a string incrementally, strings.Builder is the usual best tool.

go
1package main
2
3import (
4    "fmt"
5    "strings"
6)
7
8func main() {
9    words := []string{"Go", "builds", "strings", "efficiently"}
10
11    var builder strings.Builder
12    for i, word := range words {
13        if i > 0 {
14            builder.WriteString(" ")
15        }
16        builder.WriteString(word)
17    }
18
19    fmt.Println(builder.String())
20}

A builder reduces the number of temporary strings created during repeated concatenation.

Use strings.Join When You Already Have a Slice

If the data is already a slice of strings and you want a separator between elements, strings.Join is usually the cleanest and fastest answer.

go
1package main
2
3import (
4    "fmt"
5    "strings"
6)
7
8func main() {
9    parts := []string{"api", "v1", "users"}
10    path := strings.Join(parts, "/")
11    fmt.Println(path)
12}

This is more direct than manually looping with a builder for a simple join operation.

Avoid fmt.Sprintf for Pure Concatenation

fmt.Sprintf is useful for formatting mixed values, but it is not the best choice when the only goal is to join strings.

go
1package main
2
3import "fmt"
4
5func main() {
6    name := "Ava"
7    age := 30
8    message := fmt.Sprintf("%s is %d years old", name, age)
9    fmt.Println(message)
10}

Use it when formatting matters. Do not reach for it as a default replacement for concatenation.

Pre-Grow the Builder When Size Is Known

If you can estimate the final string length, growing the builder up front can cut down on reallocations.

go
1package main
2
3import (
4    "fmt"
5    "strings"
6)
7
8func main() {
9    parts := []string{"alpha", "beta", "gamma"}
10
11    var builder strings.Builder
12    builder.Grow(len("alpha,beta,gamma"))
13
14    for i, part := range parts {
15        if i > 0 {
16            builder.WriteString(",")
17        }
18        builder.WriteString(part)
19    }
20
21    fmt.Println(builder.String())
22}

This matters mainly in performance-sensitive code paths, not in normal application glue code.

Measure When Performance Actually Matters

Concatenation advice is easy to overstate. If string building is part of a critical path, confirm with benchmarks instead of guessing.

go
1func BenchmarkBuilder(b *testing.B) {
2    for i := 0; i < b.N; i++ {
3        var builder strings.Builder
4        builder.WriteString("a")
5        builder.WriteString("b")
6        builder.WriteString("c")
7        _ = builder.String()
8    }
9}

Go makes benchmarking cheap. Use that instead of relying on folklore.

A small benchmark often settles the question faster than debate, especially when input size and separator behavior vary across real workloads.

Common Pitfalls

  • Repeatedly using + inside loops and creating many temporary strings.
  • Reaching for fmt.Sprintf when no formatting is needed.
  • Manually looping when strings.Join already matches the problem exactly.
  • Over-optimizing tiny string operations that are not on a hot path.
  • Skipping benchmarks and assuming one method is always fastest in every context.

Summary

  • Use + for small, fixed concatenations.
  • Use strings.Builder for incremental string construction.
  • Use strings.Join for slices of strings with a separator.
  • Use fmt.Sprintf when formatting values, not just joining text.
  • Benchmark real hot paths before treating concatenation style as a performance issue.

Course illustration
Course illustration

All Rights Reserved.