字符串拼接
在 Golang 语言中 , 关于字符串拼接有多种方式 , 分别是:
- 使用操作符
- +/+=
- 使用
- fmt.Sprintf
- 使用
- bytes.Buffer
- 使用
- strings.Join
- 使用
- strings.Builder
使用 拼接字符串 , 性能是最差的 , 但是它可以格式化 , 所以一般使用场景是需要格式化拼接字符串 。
fmt.Sprintf
使用 和使用 的性能比较接近 , 性能最高的字符串拼接方式是使用 。
bytes.Buffer
strings.Join
strings.Builder
我准备对 的字符串拼接方式多费些笔墨 。
strings.Builder
Golang 语言标准库 strings 中的 Builder 类型 , 用于在 Write 方法中有效拼接字符串 , 它减少了数据拷贝和内存分配 。
Builder 结构体中包含两个字段 , 分别是 addr 和 buf , 字段 addr 是指针类型 , 字段 buf 是字节切片类型 , 但是它的值仍然不允许被修改 , 但是字节切片中的值可以被拼接或者被重置 。
Builder 提供了一系列 Write* 拼接方法 , 这些方法可以用于把新数据拼接到已存在的数据的末尾 , 同时如果字节切片的容量不够用 , 可以自动扩容 。 需要注意的是 , 只要触发扩容 , 就会涉及内存分配和数据拷贝 。 自动扩容规则和切片的扩容规则相同 。
除了自动扩容 , 还可以手动扩容 , Builder 提供的 Grow 方法 , 可以根据 int 类型的传参 , 扩充字节数量 。 因为扩容操作 , 会涉及内存分配和数据拷贝 , 所以调用 Grow 方法手动扩容时 , Golang 也做了优化 , 如果当前字节切片的容量剩余字节数小于或等于传参的值 ,Grow 方法将不会执行扩容操作 。 手动扩容规则是原字节切片容量的 2 倍加上传参的值 。
Builder 类型还提供了一个重置方法 Reset , 它可以将 Builder 类型的变量重置为零值 。 被重置后 , 原字节切片将会被垃圾回收 。
在了解完上述 Builder 的介绍后 , 相信读者已对 Builder 有了初步认识 。 下面我们通过代码看一下预分配字节数量和未分配字节数量的区别:
阅读上面这段代码 , 可以发现调用 Grow 方法 , 预分配字节数量比未预分配字节数量的字符串拼接效率高 。 我们在可以预估字节数量的前提下 , 尽量使用 Grow 方法预先分配字节数量 。
字符串和字节切片互相转换
- 注意:第一 , Builder 类型的变量在被调用之后 , 不可以再被复制 , 否则会引发 panic 。 第二 , 因为 Builder 类型的值不是完全不可修改的 , 所以使用者需要注意并发安全的问题 。
因为切片类型除了只能和 nil 做比较之外 , 切片类型之间是无法做比较操作的 。 如果我们需要对切片类型做比较操作 , 通常的做法是先将切片类型转换为字符串类型 。 但是因为 string 类型是只读的 , 不可修改的 , 所以转换操作会涉及内存分配和数据拷贝 。
为了提升转换的性能 , 唯一的方法就是减少或者避免内存分配的开销 。 在 Golang 语言中 , 运行时对二者的互相转换也做了优化 , 感兴趣的读者可以阅读 runtime 中的相关源码:
/usr/local/go/src/runtime/string.go
但是 , 我们还可以继续优化 , 实现零拷贝的转换操作 , 从而避免内存分配的开销 , 提升转换效率 。
- rest|golang笔记 | 面试题整理
- 文艺辣评丨新东方直播:一场语言的行为艺术?
- c语言|负责任地推荐这3部手机,好看又配置强,用到2026年不成问题
- C++|三星将推出OneUI5.0测试版,S22首测,新系统更流畅!
- C++|大周建议自媒体新手小白博主前期做这4件事!
- C++|国产杀毒软件为何没落了?前世今生连起来看,就是互联网版宫廷剧
- 京东|Java:有哪些快速学习Java语言的技巧?
- C++|李明杰为优投创业营公开课做IP打造的专题分享
- 红杉资本|广州蓝景技术分享—开发语言JavaScript之多线程
- 诺基亚|听人话生成代码厉害了,国内首个自然语言生成方法级代码的AI
