Go中拼接字符串应避免循环内用+,推荐strings.Builder(零拷贝、可预分配)、fmt.Sprintf(适合少量格式化)、strings.Join(已有切片时最高效)。

Go 里拼接字符串不能用 + 随意连写多次,尤其在循环中——这会触发大量内存分配和拷贝,性能崩得很快。
用 strings.Builder 拼接大量字符串(推荐)
这是 Go 1.10+ 官方主推的方式,底层复用 []byte 缓冲区,零拷贝、无 GC 压力。
- 适合:日志组装、HTML 模板生成、批量 SQL 构建等需多次追加的场景
- 必须调用
builder.String()获取结果,不能重复使用同一实例(除非调用builder.Reset()) - 初始化时可传入预估容量(如
strings.Builder{Cap: 1024}),避免多次扩容
var builder strings.Builder
builder.Grow(256) // 预分配空间
builder.WriteString("Hello")
builder.WriteString(" ")
builder.WriteString("World")
result := builder.String() // "Hello World"
用 fmt.Sprintf 拼接少量固定格式字符串
语法简洁,适合模板化拼接(比如带变量的提示信息),但每次调用都会分配新字符串,不适合高频或大数据量。
- 注意:
fmt.Sprintf是通用格式化函数,不是专为拼接设计;参数类型不匹配会导致 panic(如用%d格式化字符串) - 没有编译期检查,建议只用于调试输出或低频构造
- 比
strings.Builder慢约 3–5 倍(基准测试数据)
name := "Alice"
age := 30
msg := fmt.Sprintf("User: %s, Age: %d", name, age) // "User: Alice, Age: 30"
用 strings.Join 拼接已知切片
当你已有 []string,且只需加一个分隔符(如逗号、换行),这是最直接、最高效的方式。
立即学习“go语言免费学习笔记(深入)”;
- 底层是单次分配 + 一次拷贝,时间复杂度 O(n)
- 如果切片为空,返回空字符串;如果切片只有一个元素,直接返回该元素(不加分割符)
- 不要为了用它而先把字符串拆成切片再 join——那反而多一次分配
parts := []string{"apple", "banana", "cherry"}
result := strings.Join(parts, ", ") // "apple, banana, cherry"
避免用 + 在循环中拼接
每次 + 都创建新字符串,底层复制前序所有字节。N 次循环 → O(N²) 时间复杂度,内存占用爆炸。
- 错误示例:
for _, s := range list { result += s } - 即使只有 100 个长度 100 的字符串,也会分配约 500KB 内存并执行数万次拷贝
- 静态字符串常量拼接(如
"a" + "b" + "c")会被编译器优化成单个字符串,没问题
// ❌ 危险
var s string
for i := 0; i < 1000; i++ {
s += strconv.Itoa(i) // 每次都重新分配
}
// ✅ 改用 Builder
var b strings.Builder
for i := 0; i < 1000; i++ {
b.WriteString(strconv.Itoa(i))
}
s := b.String()
真正要注意的是拼接发生的上下文:循环次数、字符串平均长度、是否复用缓冲区。哪怕用了 strings.Builder,忘了 Grow 或反复新建实例,照样掉进性能坑里。










