一篇帶你看懂Go語言中的字符串拼接(小白入門)
在 Go 里:
字符串 string 是不可變的(你不能在原來的 string 上直接改)
所以 用 + / += 反復拼接,經(jīng)常會很慢(反復分配 + 復制)
為了快,Go 常用兩種方式:
- 用
[]byte+append拼 - 用
strings.Builder拼(寫法更像“拼字符串”,性能也好)
cap / Grow 都是在做同一件事:提前預留容量,減少擴容拷貝
1. 為什么“拼字符串”會出問題?
你想要構造一個輸出,比如:
"blue is sky the"
最直覺的寫法是:
ans := "" ans += "blue" ans += " " ans += "is"
看起來很合理對吧?
但 Go 的 string 有個關鍵特性:
Go 的 string 不可變(immutable)
你一旦創(chuàng)建了一個 string,它里面的內(nèi)容不能“原地修改”。
所以 ans += "blue" 實際發(fā)生的是:
- 新開一塊內(nèi)存,長度 = oldLen + newLen
- 把舊的
ans復制進去 - 再把
"blue"復制進去 - 把
ans指向這塊新內(nèi)存
也就是說:每一次 += 都可能要“重新開數(shù)組 + 復制一遍舊內(nèi)容”
2. 這就是為什么+會慢:重復拷貝
舉個特別直觀的例子:
你要拼 3 次:
- 第 1 次:復制 0 個舊字符
- 第 2 次:復制 4 個舊字符("blue")
- 第 3 次:復制 7 個舊字符("blue is")
你會發(fā)現(xiàn):舊內(nèi)容一直在被反復復制。
拼得越多,復制越多,速度就越慢。
3. 那怎么快?核心思路:用“可變?nèi)萜?rdquo;先裝起來
既然 string 不可變,那我們先用一個 可變的容器 裝字符,最后一次性變成 string。
Go 最常用的可變?nèi)萜骶褪牵?/p>
[]byte(字節(jié)數(shù)組 / 可變)
你可以對它 append,它會自動增長:
ans := make([]byte, 0) ans = append(ans, 'b', 'l', 'u', 'e')
最后:
return string(ans)
這樣就避免了每次 += 的“重新分配 + 復制舊內(nèi)容”。
4. 這就引出了:len和cap是啥?
[]byte / []int 這些 slice,在 Go 里有兩個重要概念:
len:現(xiàn)在已經(jīng)用了多少cap:底層總共預留了多少空間(還能裝多少)
比如:
ans := make([]byte, 0, 10)
意思是:
len = 0(現(xiàn)在里面沒東西)cap = 10(底層數(shù)組先預留了 10 個位置)
為什么要 cap?
因為如果你不預留,append 可能會這樣:
- 空間不夠 → 申請更大數(shù)組
- 把舊數(shù)組內(nèi)容復制過去
- 才能繼續(xù) append
所以:
cap 就是為了減少“擴容 + 拷貝”的次數(shù)。
5. 超過 cap 會發(fā)生什么?
當你 append 讓 len > cap:
- Go 會創(chuàng)建一個更大的新數(shù)組
- 把舊內(nèi)容復制到新數(shù)組
- slice 指向新數(shù)組
你看:又出現(xiàn)“復制舊內(nèi)容”了對吧?
所以我們才要 盡量提前預留 cap。
6. 這時候strings.Builder登場:更“像拼字符串”的工具
你用 []byte 拼字符串沒問題,但寫起來像在操作數(shù)組。 strings.Builder 是 Go 官方提供的:
專門用來高效拼接字符串的工具
你可以把它理解成:
“官方封裝好的[]byte + append”
它的用法是:
import "strings"
var b strings.Builder
b.WriteString("blue")
b.WriteByte(' ')
b.WriteString("sky")
result := b.String()
你可以把它理解成:
“內(nèi)部幫你維護了一個 []byte 的拼接器”
你 WriteString/WriteByte,它內(nèi)部就在 append 到那個 buffer 里。
最后 String() 一次性輸出。
7. 那Grow又是什么?它和cap的關系是什么?
現(xiàn)在關鍵來了:
Builder 內(nèi)部其實也需要容量,否則也會擴容 + 拷貝。
所以它也需要“預留空間”。
這就是:
b.Grow(n)
意思是:
提前保證:接下來還能再寫 n 個字節(jié),不用擴容
對應到 slice 的感覺就是:
- slice:
make([]byte, 0, n)預留 cap - builder:
b.Grow(n)預留內(nèi)部 buffer 的 cap
所以它們關系是:
Grow 本質(zhì)上是在給 Builder 內(nèi)部的“隱藏 slice”擴 cap。
9. 小白怎么選
你現(xiàn)在階段記住這個就夠了:
簡單場景(拼得不多)
用 + 也行(比如 2~3 次拼接)
循環(huán)里大量拼接(比如這題、構造大字符串)
優(yōu)先用:
strings.Builder(推薦,易讀)
或[]byte+append(你已經(jīng)在用)
追求性能時加一條:預留容量
ans := make([]byte, 0, len(s))b.Grow(len(s))
到此這篇關于一篇帶你看懂Go語言中的字符串拼接(小白入門)的文章就介紹到這了,更多相關Go字符串拼接內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
詳解Golang實現(xiàn)http重定向https的方式
這篇文章主要介紹了詳解Golang實現(xiàn)http重定向https的方式,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-08-08
go-zero接入skywalking實現(xiàn)鏈路追蹤的詳細教程
SkyWalking是一個開源的服務追蹤系統(tǒng),它專注于分布式系統(tǒng)的可觀測性和服務性能分析,它的主要目標是幫助開發(fā)者理解和優(yōu)化微服務架構中的服務間交互情況,本文介紹了go-zero接入skywalking鏈路追蹤的詳細教程,需要的朋友可以參考下2024-08-08

