字符串拼接

axing
2025-09-25 / 0 评论 / 4 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2025年09月25日,已超过18天没有更新,若内容或图片失效,请留言反馈。

一、字符串拼接
1.1 + 运算

s2 := s1 + name
优点:最直观,少量片段时也最快。单个表达式里 a + b + c 编译器会预估长度、仅一次分配。
注意:在循环中做 s += part 会导致多次分配与拷贝(可能退化 O(n^2)),应改为 Builder/Buffer 或先收集后 Join。
适用:2–5 个固定小片段、对性能要求一般的场景;常量拼接会在编译期完成(零开销)。

1.2 strings.Join

d4 := strings.Join([]string{d1, d2}, ",")
优点:已在切片里、有统一分隔符(如 ,、|、空串)时,一次性预分配,通常是多段连接的首选。
适用:CSV/日志行拼接、URL path/标签列表、SQL 占位符 "?,?,?" 之类模式。
小技巧:先 make([]string, 0, n) 收集,再 strings.Join(parts, sep) 可减少切片扩容。

1.3 fmt.Sprintf

d3 := fmt.Sprintf("%s,%s", d1, d2)
// 优点:格式化强、跨类型方便(%d、%.2f、对齐宽度等)。
// 缺点:需要解析格式串,最慢、分配也更多。
// 适用:确实需要格式化能力(尤其跨类型)时;在性能敏感路径尽量用 strconv/Builder 代替:
var b strings.Builder
b.WriteString(name)
b.WriteByte(',')
b.WriteString(strconv.Itoa(age))
s := b.String()

1.4 bytes.Buffer

var buffer bytes.Buffer
buffer.WriteString("tom")
buffer.WriteString(",")
buffer.WriteString("20")
s := buffer.String()
优点:实现了 io.Writer,与其它 Writer/Reader 组合很方便,既可写字符串也可写字节。
注意:buffer.String() 会拷贝内部 []byte 生成字符串(因此会有一次分配)。
适用:需要同时处理 []byte、或与文件/网络/压缩流等 IO 组件对接时;如果最终只要 string,通常改用 strings.Builder 更省。

1.5 strings.Builder

var sb strings.Builder
sb.Grow(64)              // 可选:大致预估长度
sb.WriteString("tom")
sb.WriteByte(',')
sb.WriteString("20")
s := sb.String()         // 通常零拷贝拿到字符串
优点:零值可用;为构造字符串而生,String() 返回结果通常不拷贝底层数据;也实现 io.Writer。
注意:不要拷贝已使用过的 Builder(按值传递会出问题);非并发安全。
适用:循环里逐步构建字符串、性能敏感路径、最终产出是 string 的情况。

二、常见场景的推荐写法
2.1 循环里累计很多片段(性能敏感)

//用 strings.Builder 或 bytes.Buffer(只要字符串就用 Builder)
var b strings.Builder
b.Grow(1024) // 如果能粗略估计长度
for _, p := range parts {
    b.WriteString(p)
    b.WriteByte(',')
}
s := b.String()

2.2 已有切片 + 统一分隔符 (用 strings.Join)

s := strings.Join(parts, ",")

2.3 少量固定片段 用 +

s := "hello " + name

2.4 需要格式化/跨类型

// 用 fmt.Sprintf(或 strconv + Builder 更高性能)
s := fmt.Sprintf("%s(%d)", name, age)
// 或
var b strings.Builder
b.WriteString(name)
b.WriteByte('(')
b.WriteString(strconv.Itoa(age))
b.WriteByte(')')
s := b.String()

2.5 小坑与小技巧

- +/Sprintf 都不适合在大循环内反复累加;会频繁分配。

- strings.Builder/bytes.Buffer 都不是并发安全;不要在多个 goroutine 同时写。

- strings.Builder 的实例不要复制(作为函数参数请传指针或在内部新建)。

- bytes.Buffer 的 String() 每次都会生成新字符串;避免在热路径里对同一个 Buffer 反复 String()。

- 需要固定宽度、小数位、对齐等格式控制时,fmt 家族清晰可读;对极致性能,优先 strconv.Append* 系列 + Builder/Buffer。

三、转义字符
mfzgfxjv.png

0

评论 (0)

取消