bufio 把多次小 I/O 合併成一次大 I/O,大幅降低系統呼叫成本。

緩衝讀取#

import "bufio"

file, _ := os.Open("large_file.txt")
reader := bufio.NewReader(file)

// 按行讀取
for {
    line, err := reader.ReadString('\n')
    if err == io.EOF {
        break
    }
    if err != nil {
        log.Fatal(err)
    }
    fmt.Print(line)
}

// 或使用 Scanner(更簡潔)
file.Seek(0, 0)
scanner := bufio.NewScanner(file)
for scanner.Scan() {
    fmt.Println(scanner.Text())
}

緩衝寫入#

file, _ := os.Create("output.txt")
writer := bufio.NewWriter(file)

writer.WriteString("Hello\n")
writer.WriteString("World\n")

// 必須刷新緩衝區
writer.Flush()
file.Close()

使用 bufio.Writer 時,必須在結束前呼叫 Flush() 確保所有資料都被寫入。否則緩衝區中的資料可能會遺失。

Scanner 分詞器#

// 預設按行分割
scanner := bufio.NewScanner(strings.NewReader("word1 word2 word3"))

// 改為按單詞分割
scanner.Split(bufio.ScanWords)

for scanner.Scan() {
    fmt.Println(scanner.Text())  // word1, word2, word3
}

// 內建的分割函式
// bufio.ScanLines  - 按行(預設)
// bufio.ScanWords  - 按單詞
// bufio.ScanRunes  - 按 rune
// bufio.ScanBytes  - 按位元組
自訂分割函式
// 以逗號分割
splitComma := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
    if atEOF && len(data) == 0 {
        return 0, nil, nil
    }
    if i := bytes.IndexByte(data, ','); i >= 0 {
        return i + 1, data[0:i], nil
    }
    if atEOF {
        return len(data), data, nil
    }
    return 0, nil, nil
}

scanner := bufio.NewScanner(strings.NewReader("a,b,c,d"))
scanner.Split(splitComma)
for scanner.Scan() {
    fmt.Println(scanner.Text())  // a, b, c, d
}