bufio 包详解#
bufio 是 Go 标准库中的一个包,提供了带缓冲的 I/O 操作功能。它可以包装现有的 io.Reader 和 io.Writer 对象,创建具有缓冲功能的对象,从而提高 I/O 操作的效率。
核心概念#
缓冲 I/O 的优势#
- 减少系统调用:通过缓冲数据,减少实际的 I/O 操作次数
- 提高性能:特别是对于小数据量的频繁读写操作
- 提供更方便的接口:如按行读取等功能
主要类型和方法#
1. Reader#
bufio.Reader 为读取操作提供缓冲。
</>
go
1func NewReader(rd io.Reader) *Reader
2func NewReaderSize(rd io.Reader, size int) *Reader常用方法:
Read(p []byte) (n int, err error)- 读取数据到 pReadByte() (byte, error)- 读取一个字节ReadBytes(delim byte) ([]byte, error)- 读取直到遇到 delimReadLine() (line []byte, isPrefix bool, err error)- 读取一行ReadString(delim byte) (string, error)- 读取字符串直到 delimPeek(n int) ([]byte, error)- 预览前 n 个字节但不移动读取位置Reset(r io.Reader)- 重置 Reader 以读取新的输入源
2. Writer#
bufio.Writer 为写入操作提供缓冲。
</>
go
1func NewWriter(w io.Writer) *Writer
2func NewWriterSize(w io.Writer, size int) *Writer常用方法:
Write(p []byte) (nn int, err error)- 写入 pWriteByte(c byte) error- 写入一个字节WriteRune(r rune) (size int, err error)- 写入一个 runeWriteString(s string) (int, error)- 写入字符串Flush() error- 刷新缓冲区,确保所有数据已写入底层 WriterAvailable() int- 返回缓冲区中未使用的字节数Buffered() int- 返回已缓冲但未写入的字节数Reset(w io.Writer)- 重置 Writer 以写入新的目标
3. Scanner#
bufio.Scanner 提供了更方便的逐行或按分隔符读取的接口。
</>
go
1func NewScanner(r io.Reader) *Scanner常用方法:
Scan() bool- 扫描下一个 tokenText() string- 返回扫描到的文本Bytes() []byte- 返回扫描到的字节Split(split SplitFunc)- 设置分割函数
预定义的分割函数:
ScanLines- 按行分割(默认)ScanWords- 按单词分割ScanRunes- 按 rune 分割ScanBytes- 按字节分割
使用示例#
Reader 示例#
</>
go
1package main
2
3import (
4 "bufio"
5 "fmt"
6 "strings"
7)
8
9func main() {
10 s := strings.NewReader("Hello\nWorld\nGoodbye")
11 reader := bufio.NewReader(s)
12
13 for {
14 line, err := reader.ReadString('\n')
15 if err != nil {
16 break
17 }
18 fmt.Print(line)
19 }
20}Writer 示例#
</>
go
1package main
2
3import (
4 "bufio"
5 "os"
6)
7
8func main() {
9 file, _ := os.Create("output.txt")
10 defer file.Close()
11
12 writer := bufio.NewWriter(file)
13 writer.WriteString("Hello, ")
14 writer.WriteString("World!\n")
15 writer.Flush() // 必须调用 Flush 确保数据写入文件
16}Scanner 示例#
</>
go
1package main
2
3import (
4 "bufio"
5 "fmt"
6 "strings"
7)
8
9func main() {
10 s := strings.NewReader("Hello World\nGoodbye Moon")
11 scanner := bufio.NewScanner(s)
12
13 for scanner.Scan() {
14 fmt.Println(scanner.Text())
15 }
16
17 if err := scanner.Err(); err != nil {
18 fmt.Println("Error:", err)
19 }
20}性能考虑#
- 缓冲区大小:默认缓冲区大小是 4096 字节,对于特定场景可以调整
- 及时 Flush:写入操作后记得调用 Flush,或使用
defer writer.Flush() - 错误处理:注意检查 Peek 和 Read 等操作的错误
- 重用对象:可以使用 Reset 方法重用 Reader/Writer 以减少分配
常见使用场景#
- 逐行读取文件
- 高效写入大量小数据
- 网络通信中的缓冲读写
- 解析文本数据
- 实现自定义的协议解析
bufio 包是 Go 中处理 I/O 操作的重要工具,合理使用可以显著提高程序性能。