Go 字串拼接常見方式
Go 中常見的字串拼接方式有五種,依效能大致排序如下:
info
效能排序(快 → 慢):
strings.Join ≈ strings.Builder > bytes.Buffer > + > fmt.Sprintf
+ 運算子
- 每次拼接都會建立新字串,需重新配置並複製內容。
- 寫法直觀,但效能較差,不適合大量或迴圈內拼接。
fmt.Print("thomas" + " test") // output:thomas test
fmt.Sprintf
- 使用介面與反射,語法簡潔、可格式化。
- 效能通常最差,僅適合偶爾、可讀性優先的場合。
package main
import "fmt"
func main() {
// 純字串拼接
s := fmt.Sprintf("%s%s%s", "a", "b", "c") // "abc"
// 搭配數字、布林等格式化
msg := fmt.Sprintf("user=%s, count=%d, ok=%v", "alice", 42, true)
// "user=alice, count=42, ok=true"
// 小數位數、補零等
num := fmt.Sprintf("%.2f", 3.14159) // "3.14"
code := fmt.Sprintf("%04d", 7) // "0007"
_, _, _, _ = s, msg, num, code
}
info
%s、%d、%v 是什麼
| 動詞 | 意思 | 適合型別 | 範例輸出 |
|---|---|---|---|
| %s | string,把值當字串印出 | string | "alice" |
| %d | decimal integer,十進位整數 | int, int32, int64 等整數 | 42 |
| %v | value,用預設、通用格式印出 | 任意型別 | — |
| %f | floating-point number,浮點數 | float32, float64 | 3.14 |
| %t | boolean,布林值 | bool | true |
| %c | character,字元 | rune | 'a' |
| %p | pointer,指標 | *T | &x |
| %x | hexadecimal,十六進位 | int, int32, int64 等整數 | 0x1234 |
| %o | octal,八進位 | int, int32, int64 等整數 | 0123 |
| %b | binary,二進位 | int, int32, int64 等整數 | 101010 |
| %e | scientific notation,科學記數法 | float32, float64 | 1.234567e+08 |
| %g | general number,通用數字格式 | float32, float64 | 1.234567 |
| %q | quoted string,引號字串 | string | "hello" |
| %T | type,型別 | 任意型別 | int |
| %U | Unicode code point,Unicode 碼點 | int32 | U+0041 |
| %w | width,寬度 | int | 10 |
| %0 | padding,填補 | int | 0123 |
| %* | flag,旗標 | bool | true |
strings.Builder
- 內部以
[]byte緩衝區累加,最後一次轉成string,避免多次拷貝。 - 適合迴圈或多次拼接,為官方推薦的高效方式。
var sb strings.Builder
sb.WriteString("a")
sb.WriteString("b")
sb.WriteString("c")
ret := sb.String()
// output: abc
bytes.Buffer
- 同樣基於
[]byte的緩衝器,可處理位元組與字串,亦可轉成string。 - 效能略遜於
strings.Builder,若同時需要 I/O 或位元組操作時可選用。
package main
import "bytes"
func main() {
var buf bytes.Buffer
// 字串寫入
buf.WriteString("a")
buf.WriteString("b")
// 位元組寫入(適合混用 []byte 與 string)
buf.Write([]byte("c"))
// 轉成 string
ret := buf.String() // "abc"
_ = ret
}
strings.Join
- 底層以
strings.Builder實作,並會預先依長度呼叫Grow做容量規劃。 - 對已知的
[]string片段拼接非常高效,語法最簡潔。
ret := strings.Join([]string{"a", "b", "c"}, "")
綜合範例
同一組字串 ["a","b","c"] 用五種方式拼接的對照:
package main
import (
"bytes"
"fmt"
"strings"
)
func main() {
a := []string{"a", "b", "c"}
// 方式 1:+
ret1 := a[0] + a[1] + a[2]
// 方式 2:fmt.Sprintf
ret2 := fmt.Sprintf("%s%s%s", a[0], a[1], a[2])
// 方式 3:strings.Builder
var sb strings.Builder
sb.WriteString(a[0])
sb.WriteString(a[1])
sb.WriteString(a[2])
ret3 := sb.String()
// 方式 4:bytes.Buffer
buf := new(bytes.Buffer)
buf.WriteString(a[0])
buf.WriteString(a[1])
buf.WriteString(a[2])
ret4 := buf.String()
// 方式 5:strings.Join
ret5 := strings.Join(a, "")
_, _, _, _, _ = ret1, ret2, ret3, ret4, ret5
}
參考:極客兔兔《字串拼接效能及原理 | Go 語言高效能程式設計》