golang的字串拼接

來源:互聯網
上載者:User

常用拼接方法

字串拼接在日常開發中是很常見的需求,目前有兩種普遍做法:

一種是直接用 += 來拼接

s1 := "Hello"s2 := "World"s3 := s1 + s2  // s3 == "HelloWorld"s1 += s2       // s1 == "HelloWorld"

這是最常用也是最簡單直觀的方法,不過簡單是有代價的,golang的字串是不可變類型,也就是說每一次對字串的“原地”修改都會重建一個string,再把資料複製進去,這樣一來將會產生很可觀的效能開銷,稍後的效能測試中將會看到這一點。

 

第二種是使用bytes.Buffer

// bytes.Buffer的0值可以直接使用var buff bytes.Buffer// 向buff中寫入字元/字串buff.Write([]byte("Hello"))buff.WriteByte(' ')buff.WriteString("World")// String() 方法獲得拼接的字串buff.String() // "Hello World"

這種方法用於需要大量進行字串拼接操作的場合,效能要大大優於第一種方法。

 

不過使用bytes模組來操作string難免讓人產生迷惑,所以在go1.10中新增了第三種方法:strings.Builder,官方鼓勵盡量在string的拼接時使用Builder,byte拼接時使用Buffer

// strings.Builder的0值可以直接使用var builder strings.Builder// 向builder中寫入字元/字串builder.Write([]byte("Hello"))builder.WriteByte(' ')builder.WriteString("World")// String() 方法獲得拼接的字串builder.String() // "Hello World"

從上面的代碼中可以看到,strings.Builder和bytes.Buffer的操作幾乎一樣,不過strings.Builder僅僅實現了write類方法,而Buffer是可讀可寫的。

所以strings.Builder僅用於拼接/構建字串

效能

除了是否易用外,另一條參考標準就是效能,得益於golang內建的測試載入器,我們可以大致對比一下三種方案的效能。

測試使用從26個大寫和小寫字母10個數字以及5個常用符號共67字元中隨機取10個組成string或[]byte,再由Buffer和Builder進行拼接。

先上測試結果

go test -bench=. -benchmem

 

下面是測試代碼

// BenchmarkSpliceAddString10 測試使用 += 拼接N次長度為10的字串func BenchmarkSpliceAddString10(b *testing.B) {    s := ""    for i := 0; i < b.N; i++ {        s += GenRandString(10)    }}// BenchmarkSpliceBuilderString10 測試使用strings.Builder拼接N次長度為10的字串func BenchmarkSpliceBuilderString10(b *testing.B) {    var builder strings.Builder    for i := 0; i < b.N; i++ {        builder.WriteString(GenRandString(10))    }}// BenchmarkSpliceBufferString10 測試使用bytes.Buffer拼接N次長度為10的字串func BenchmarkSpliceBufferString10(b *testing.B) {    var buff bytes.Buffer    for i := 0; i < b.N; i++ {        buff.WriteString(GenRandString(10))    }}// BenchmarkSpliceBufferByte10 測試使用bytes.Buffer拼接N次長度為10的[]bytefunc BenchmarkSpliceBufferByte10(b *testing.B) {    var buff bytes.Buffer    for i := 0; i < b.N; i++ {        buff.Write(GenRandBytes(10))    }}// BenchmarkSpliceBuilderByte10 測試使用string.Builder拼接N次長度為10的[]bytefunc BenchmarkSpliceBuilderByte10(b *testing.B) {    var builder strings.Builder    for i := 0; i < b.N; i++ {        builder.Write(GenRandBytes(10))    }}

這是產生供拼接使用的隨機字串的代碼(這裡仍然使用了bytes.Buffer,推薦使用新的strings.Builder)

const (    data = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890,.-=/")func init() {    rand.Seed(time.Now().Unix()) // 設定隨機種子}// GenRandString 產生n個隨機字元的stringfunc GenRandString(n int) string {    max := len(data)    var buf bytes.Buffer    for i := 0; i < n; i++ {        buf.WriteByte(data[rand.Intn(max)])    }    return buf.String()}// GenRandBytes 產生n個隨機字元的[]bytefunc GenRandBytes(n int) []byte {    max := len(data)    buf := make([]byte, n)    for i := 0; i < n; i++ {        buf[i] = data[rand.Intn(max)]    }    return buf}

 

使用 += 的方法效能是最慢的,效能和其他兩種差了好幾個數量級。

Buffer和Builder效能相差無幾,Builder在記憶體的使用上要略優於Buffer

結論

strings.Builder在golang 1.10才引入標準庫的,所以 version <= 1.9 的時候對於大量字串的拼接操作推薦bytes.Buffer

如果你正在使用1.10+,那麼建議使用strings.Builder,不僅是更好的效能,也是為了能使代碼更清晰。

當然,對於簡單的拼接,+= 就足夠了

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.