strings.Builder#

strings.Builder 是用於高效建構字串的型別:

import "strings"

var builder strings.Builder

builder.WriteString("Hello, ")
builder.WriteString("World!")
builder.WriteByte('!')
builder.WriteRune('🎉')

result := builder.String()  // "Hello, World!!🎉"
fmt.Println(builder.Len())  // 目前長度

為什麼使用 strings.Builder

Go 的字串是不可變的,每次以 + 串接都會建立新字串並複製內容。strings.Builder 可以避免這種重複的記憶體配置與複製。

// 低效做法(大量記憶體配置)
s := ""
for i := 0; i < 1000; i++ {
    s += "a"  // 每次都建立新字串
}

// 高效做法
var builder strings.Builder
for i := 0; i < 1000; i++ {
    builder.WriteString("a")
}
s := builder.String()

內部機制#

strings.Builder 內部用 []byte 切片儲存內容:

type Builder struct {
    addr *Builder  // 用於檢測非法複製
    buf  []byte    // 內部緩衝區
}
預分配緩衝區

若知道最終字串的大致長度,可以預先分配:

var builder strings.Builder
builder.Grow(1000)  // 預分配 1000 位元組

for i := 0; i < 100; i++ {
    builder.WriteString("0123456789")
}
// 不會觸發擴容

strings.Builder 不能被複製後繼續使用。複製後呼叫方法會 panic:

var b1 strings.Builder
b1.WriteString("hello")

b2 := b1  // 複製
// b2.WriteString("world")  // panic!

strings.Reader#

strings.Reader 讓字串實作 io.Reader 等介面:

reader := strings.NewReader("Hello, World!")

// 實作的介面
// io.Reader, io.ReaderAt, io.WriterTo
// io.Seeker, io.ByteScanner, io.RuneScanner

buf := make([]byte, 5)
n, _ := reader.Read(buf)  // n=5, buf="Hello"

// 重置讀取位置
reader.Reset("New content")

常用字串函式#

s := "Hello, World!"

// 查找
strings.Contains(s, "World")     // true
strings.HasPrefix(s, "Hello")    // true
strings.HasSuffix(s, "!")        // true
strings.Index(s, "o")            // 4
strings.LastIndex(s, "o")        // 8

// 轉換
strings.ToUpper(s)               // "HELLO, WORLD!"
strings.ToLower(s)               // "hello, world!"
strings.TrimSpace("  hi  ")      // "hi"
strings.Trim(s, "!")             // "Hello, World"

// 分割與連接
parts := strings.Split("a,b,c", ",")   // ["a", "b", "c"]
joined := strings.Join(parts, "-")      // "a-b-c"

// 替換
strings.Replace(s, "World", "Go", 1)    // "Hello, Go!"
strings.ReplaceAll(s, "l", "L")         // "HeLLo, WorLd!"

bytes.Buffer#

bytes.Buffer 提供可讀寫的位元組緩衝區:

import "bytes"

var buf bytes.Buffer

// 寫入
buf.WriteString("Hello")
buf.WriteByte(' ')
buf.Write([]byte("World"))

// 讀取
data := buf.Bytes()    // 取得內容(不消耗)
str := buf.String()    // 轉為字串

line, _ := buf.ReadBytes('\n')  // 讀取直到分隔符

Buffer vs Builder 比較#

特性bytes.Bufferstrings.Builder
用途讀寫皆可只寫
輸出[]bytestring只能 string
讀取支援 Read、ReadByte 等不支援
適用I/O 操作、資料處理字串建構
  • 只需要建構字串 ➡️ strings.Builder
  • 需要讀寫操作 ➡️ bytes.Buffer
  • 處理二進位資料 ➡️ bytes.Buffer