字符串拼接
在 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
但是 , 我们还可以继续优化 , 实现零拷贝的转换操作 , 从而避免内存分配的开销 , 提升转换效率 。
- C++|如何在工作之余增加收入?
- Java|嵌入式开发:开发实时 C++ 应用程序的5个技巧
- 人工智能语言|专家创建“新图灵测试” 能够更好评估人工智能的隐秘能力
- |华为正式确认,自研编程语言要来了,任正非:向下扎到根
- 华为“新技术”确定,自研编程语言今年发布,有望从根本上突破!
- c语言|违反常识,却很正确:创业就是要细分垄断
- C++|亚马逊不可靠?跨境电商卖家要注意了,封店潮有第一次就有第二次
- C++|618高端机销量排名:小米第2,华为第4,榜首无可撼动
- C++|反超小米和荣耀,斩获3K档性价比第一,配置“天花板”
- c语言|大半个互联网,都在“追杀”小红书