Go 庫bytes.Buffer和strings.Builder使用及性能對比
前言
字符串拼接是老生常談了。在 Go 語言中,常見的拼接字符串的方法有:用+
號,或者使用fmt
包的Sprintf
。
str1 := "a" + "b" // str1: "ab" str2 := fmt.Sprintf("%s%s", "a", "b") // str2: "ab"
字符串低層是不可修改的,所以每次拼接字符串,都需要重新分配內(nèi)存。如果需要頻繁拼接字符串,上面兩種方法可能性能低下。我們寫下壓測代碼
// 使用 + 拼接字符串 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") } }
執(zhí)行: go test -bench . -benchmem
,得到以下結(jié)果。這個壓測結(jié)果,留著跟下文的優(yōu)化后的結(jié)果做對比。
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 方法,很方便結(jié)合 Sync.Pool
使用。
區(qū)別
需要注意的是,String()
方法實現(xiàn)還是有些許區(qū)別的,摘取 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 轉(zhuǎn)成字符串,這需要另外申請內(nèi)存,而 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() }
執(zhí)行: go test -bench . -benchmem
,得到以下結(jié)果:
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)在內(nèi)存方面,差距還是很明顯的。
以上就是Go 庫bytes.Buffer和strings.Builder使用及性能對比的詳細(xì)內(nèi)容,更多關(guān)于Go bytes.Buffer對比strings.Builder的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
golang如何使用struct的tag屬性的詳細(xì)介紹
這篇文章主要介紹了golang如何使用struct的tag屬性的詳細(xì)介紹,從例子說起,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-11-11基于Golang實現(xiàn)Redis協(xié)議解析器
這篇文章主要為大家詳細(xì)介紹了如何通過GO語言編寫簡單的Redis協(xié)議解析器,文中的示例代碼講解詳細(xì),對我們深入了解Go語言有一定的幫助,需要的可以參考一下2023-03-03基于Golang實現(xiàn)Redis分布式鎖解決秒殺問題
這篇文章主要給大家介紹了使用Golang實現(xiàn)Redis分布式鎖解決秒殺問題,文中有詳細(xì)的代碼示例供大家參考,具有一定的參考價值,需要的朋友可以參考下2023-08-08