bufio.go 源码分析
bufio
包是 Go 标准库中提供缓冲 I/O 功能的模块,bufio.go
是其核心实现文件。下面我将对其主要结构和功能进行分析。
1. 核心数据结构
Reader 结构
type Reader struct {
buf []byte
rd io.Reader // reader provided by the client
r, w int // buf read and write positions
err error
lastByte int // last byte read for UnreadByte
lastRuneSize int // size of last rune read for UnreadRune
}
buf
: 缓冲区rd
: 底层读取器r
: 读取位置指针w
: 写入位置指针err
: 存储错误lastByte
,lastRuneSize
: 用于支持回退操作
Writer 结构
type Writer struct {
err error
buf []byte
n int
wr io.Writer
}
buf
: 缓冲区wr
: 底层写入器n
: 缓冲区中已写入的字节数err
: 存储错误
ReadWriter 结构
type ReadWriter struct {
*Reader
*Writer
}
组合了 Reader 和 Writer,提供双向缓冲功能。
2. 核心方法分析
Reader 方法
初始化
func NewReaderSize(rd io.Reader, size int) *Reader
func NewReader(rd io.Reader) *Reader
- 创建带缓冲的 Reader,可指定缓冲区大小
读取方法
func (b *Reader) Read(p []byte) (n int, err error)
func (b *Reader) ReadByte() (byte, error)
func (b *Reader) ReadRune() (r rune, size int, err error)
func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error)
func (b *Reader) ReadString(delim byte) (string, error)
func (b *Reader) ReadBytes(delim byte) ([]byte, error)
- 提供了多种读取方式,包括按字节、按行、按分隔符等
- 内部都使用
fill()
方法在缓冲区不足时从底层读取器填充
填充缓冲区
func (b *Reader) fill()
- 核心方法,当缓冲区数据不足时从底层读取器读取数据填充缓冲区
- 处理缓冲区滑动和重置逻辑
Writer 方法
初始化
func NewWriterSize(w io.Writer, size int) *Writer
func NewWriter(w io.Writer) *Writer
- 创建带缓冲的 Writer
写入方法
func (b *Writer) Write(p []byte) (nn int, err error)
func (b *Writer) WriteByte(c byte) error
func (b *Writer) WriteRune(r rune) (size int, err error)
func (b *Writer) WriteString(s string) (int, error)
- 提供多种写入方式
- 内部使用
b.flush()
在缓冲区满时写入底层
刷新缓冲区
func (b *Writer) Flush() error
- 将缓冲区数据写入底层写入器
- 由
Write
和WriteXXX
方法在缓冲区满时自动调用
3. 关键实现细节
缓冲区管理
- Reader 和 Writer 都维护一个环形缓冲区
- 当缓冲区不足时,Reader 会自动填充,Writer 会自动刷新
- 缓冲区大小默认为 4096 字节
性能优化
- 减少系统调用次数:通过缓冲减少直接 I/O 操作
- 内存复用:缓冲区在整个生命周期内复用
- 最小化拷贝:尽量直接操作缓冲区
错误处理
- 错误会被缓存,后续操作会直接返回该错误
- 一旦发生错误,所有操作都会失效
4. 使用场景
适用场景
- 需要高频次小数据量读写
- 需要按行或按分隔符读取
- 需要回退读取位置
不适用场景
- 大文件拷贝(使用
io.Copy
更高效) - 需要精确控制 I/O 行为的场景
5. 示例代码
Reader 示例
reader := bufio.NewReader(os.Stdin)
for {
line, err := reader.ReadString('\n')
if err != nil {
break
}
fmt.Print("Input: ", line)
}
Writer 示例
writer := bufio.NewWriter(os.Stdout)
writer.WriteString("Hello, ")
writer.WriteString("World!\n")
writer.Flush() // 必须调用 Flush 确保数据写入
bufio
通过缓冲机制显著提高了 I/O 效率,是 Go 中处理 I/O 操作的重要工具。理解其内部实现有助于更有效地使用它并避免常见陷阱。