Go字符串拼接应优先使用strings.Builder,因其内部用可增长byte切片避免重复分配和拷贝;循环中禁用+=,避免O(n²)复杂度;仅需拼接时不用bytes.Buffer,除非需读取或格式化功能。

字符串拼接为什么需要优化
Go 中字符串是不可变的,每次用 + 或 fmt.Sprintf 拼接都会创建新字符串,旧字符串等待 GC。大量拼接时,频繁分配内存、复制内容,性能明显下降,尤其在循环中。
优先用 strings.Builder
strings.Builder 是 Go 1.10+ 官方推荐的高效拼接工具。它内部维护一个可增长的 byte 切片,避免重复分配;写入方法(WriteString、Write、.WriteString)不检查错误,零开销;还支持预设容量,进一步减少扩容次数。
- 初始化时尽量指定足够容量:// 预估总长度,减少 realloc
var b strings.Builder
b.Grow(1024) - 用 WriteString 替代 +:b.WriteString("hello")
b.WriteString(" ")
b.WriteString("world") - 获取结果调用 b.String(),该方法只做一次切片转字符串,无拷贝(底层 string header 复制)
什么情况下考虑 bytes.Buffer
bytes.Buffer 功能更全(支持读、定位、格式化等),但接口带 error 返回,轻微开销;且默认初始容量小(64 字节),未预分配时扩容更频繁。仅当你需要后续读取、Seek、或混用格式化(如 fmt.Fprintf(&b, "%d", n))时才选它。
- 若只需拼接 + 输出,strings.Builder 更轻量、更快
- 若已用 bytes.Buffer 且逻辑复杂,不必强改;但新代码建议从 Builder 开始
避免常见低效写法
不要在循环里累积 +=:s += item 每次都新建字符串,时间复杂度 O(n²)。也不要无脑用 fmt.Sprintf 拼接多个变量——它要解析格式串、分配内存、还要处理类型反射。
立即学习“go语言免费学习笔记(深入)”;
- ❌ 错误示例:result := ""
for _, s := range strs { result += s } - ✅ 正确示例:var b strings.Builder
b.Grow(totalLen)
for _, s := range strs { b.WriteString(s) }
result := b.String() - 对固定结构日志或模板,也可考虑 text/template 预编译,但属于更高层优化









