开发者

Go 库bytes.Buffer和strings.Builder使用及性能对比

开发者 https://www.devze.com 2022-12-16 10:50 出处:网络 作者: 小马别过河
目录前言bytes.Buffer 和 strings.Builder用法区别性能对比前言 字符串拼接是老生常谈了。在 Go 语言中,常见的拼接字符串的方法有:用+号,或者使用fmt包的Sprintf。
目录
  • 前言
  • bytes.Buffer 和 strings.Builder
    • 用法
    • 区别
  • 性能对比

    前言

    字符串拼接是老生常谈了。在 Go 语言中,常见的拼接字符串的方法有:用+号,或者使用fmt包的Sprintf

    str1 := "a" + "b" // str1: "ab"
    str2 := fmt.Sprintf("%s%s", "a", "b") // str2: "ab"
    

    字符串低层是不可修改的,所以每次拼接字符串,都需要重新分配内存。如果需要频繁拼接字符串,上面两种方法可能性能低下。我们写下压测代码

    // 使用 + 拼接字www.devze.com符串
    func BenchmarkConcatStrWithPlus(b *testing.B) {
    	str := ""
    	for i := 0; i < b.N; i++ {
    		str += "test"
    	}
    }android
    // 使用 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

    pkgjavascript: 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方法的源码注释:

    开发者_JAVA入门// String returns the contents of the unread portion of the buffer
    // as a string. If the Buffer is a nil pointer, it returns "<nphpil>".
    //
    // 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对比strphpings.Builder的资料请关注我们其它相关文章!

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    关注公众号