前言
字符串拼接是老生常谈了。在 Go 语言中,常见的拼接字符串的方法有:用+
号,或者使用fmt
包的Sprintf
。
str1 := "a" + "b" // str1: "ab"
str2 := fmt.Sprintf("%s%s", "a", "b") // str2: "ab"
字符串低层是不可修改的,所以每次拼接字符串,都需要重新分配内存。如果需要频繁拼接字符串,上面两种方法可能性能低下。我们写下压测代码
// 使用 + 拼接字符串
func BenchmarkConcatStrWithPlus(b *testing.B) {
str := ""
for i := 0; i < b.N; i++ {
str += "test"
}
}
// 使用 Sprintf 拼接字符串
func BenchmarkConcatStrWithSprintf(b *testing.B) {
str := ""
for i := 0; i < b.N; i++ {
str = fmt.Sprintf("%s%s", str, "test")
}
}
执行: go test -bench . -benchmem
,得到以下结果。这个压测结果,留着跟下文的优化后的结果做对比。
goos: darwin
goarch: amd64
pkg: example/string
cpu: Intel(R) Core(TM) i5-1038NG7 CPU @ 2.00GHz
BenchmarkConcatStrWithPlus-8 329544 87040 ns/op 663108 B/op 1 allocs/op
BenchmarkConcatStrWithSprintf-8 308691 160075 ns/op 1241769 B/op 4 allocs/op
PASS
ok example/string 78.604s
bytes.Buffer 和 strings.Builder
用法
bytes.Buffer 和 strings.Builder 底层类似,都是用一个 []byte 类型的切片来存字符串。用法也类似,零值可以直接使用。
bytes.Buffer 拼接字符串:
var buf bytes.Buffer
// 拼接 "a" 和 "b"
buf.WriteString("a")
buf.WriteString("b")
str := buf.String() // str 等于 "ab"
strings.Builder 拼接字符串:
var sb strings.Builder
// 拼接 "a" 和 "b"
sb.WriteString("a")
sb.WriteString("b")
str := sb.String() // str 等于 "ab"
并且,两者都提供了 Reset 方法,很方便结合 Sync.Pool
使用。
区别
需要注意的是,String()
方法实现还是有些许区别的,摘取 bytes.Buffer 的String
方法的源码注释:
// String returns the contents of the unread portion of the buffer
// as a string. If the Buffer is a nil pointer, it returns "<nil>".
//
// To build strings more efficiently, see the strings.Builder type.
func (b *Buffer) String() string {
bytes.Buffer 的 String
方法会把底层 []byte 转成字符串,这需要另外申请内存,而 strings.Builder 则不用。
性能对比
// 使用 bytes.Buffer 拼接字符串
func BenchmarkConcatStrWithBuf(b *testing.B) {
var buf bytes.Buffer
for i := 0; i < b.N; i++ {
buf.WriteString("test")
}
_ = buf.String()
}
// 使用 strings.Builder 拼接字符串
func BenchmarkConcatStrWithSb(b *testing.B) {
var sb strings.Builder
for i := 0; i < b.N; i++ {
sb.WriteString("test")
}
_ = sb.String()
}
执行: go test -bench . -benchmem
,得到以下结果:
BenchmarkConcatStrWithBuf-8 87914572 17.51 ns/op 16 B/op 0 allocs/op
BenchmarkConcatStrWithSb-8 278124620 9.562 ns/op 22 B/op 0 allocs/op
PASS
ok example/string 5.442s
对比上面的压测,strings.Builder(22 B/op)、bytes.Buffer(16 B/op) 比 Sprintf(1241769 B/op)和 + 号(663108 B/op)在内存方面,差距还是很明显的。
以上就是Go 库bytes.Buffer和strings.Builder使用及性能对比的详细内容,更多关于Go bytes.Buffer对比strings.Builder的资料请关注编程网其它相关文章!