




bufio通过缓冲区减少系统调用次数来提升I/O性能,每次读写优先操作内存缓冲区,默认4096字节为平衡点,可依场景调整大小;Writer需显式Flush,Scanner等方法依赖缓冲机制,但缓冲不能替代对数据模式与资源边界的合理评估。
bufio 能提升 I/O 性能,核心就一条:用内存换系统调用次数 —— 每次 Read 或 Write 不再直连内核,而是先跟缓冲区打交道。
每次调用 conn.Read() 或 file.Read() 都会触发用户态 → 内核态切换(约 1–2μs),还要拷贝数据。而 bufio.Reader 的 Read() 方法内部逻辑是:
Read(),一次性读取 4KB(默认大小)进缓冲区比如读 1000 行日志(每行 200 字节),不带缓冲可能触发 1000 次系统调用;用 bufio.NewReader() 后,往往只需 5–10 次批量读取。
4096 是平衡点,不是银弹。它在大多数场景下兼顾内存占用与系统调用频率,但真实业务中常需调整:
bufio.NewReaderSize(conn, 2048)
65536(64KB),显著降低 write(2) 次数1024,但要接受更高系统调用开销注意:bufio.NewReaderSize() 和 bufio.NewWriterSize() 必须在初始化时指定,运行时无法修改。
bufio.Writer 的缓冲是“写入即缓存”,不显式刷出,数据就卡在内存里 —— 这不是 bug,是设计:
w.Write() 只是把数据塞进缓冲区,不保证落盘或发到对端w.Flush(),否则最后一段内容永远不出现defer w.Flush() 也不会执行 → 推荐搭配 defer func(){ _ 
= w.Flush() }() 更稳妥bufio.Writer?不安全 —— 它没做并发保护,必须加锁或每个 goroutine 独占一个实例像 reader.ReadString('\n') 或 scanner.Scan() 看似简单,实则高度依赖缓冲机制:
ReadString() 会在缓冲区里逐字节扫描,直到遇到 '\n';如果一行跨了两次底层读取,它会自动触发第二次填充 —— 你完全感知不到Peek(1) 是零拷贝预读:只看下一个字节不移动读位置,适合协议解析(如判断消息类型)Scanner 底层就是封装了 bufio.Reader,但默认缓冲区仍是 4KB;若扫描超长行(>4KB),会自动扩容,但频繁扩容有分配压力所以别以为用了 Scanner 就万事大吉 —— 如果你的日志行平均 16KB,建议初始化时传自定义 bufio.NewReaderSize(file, 65536) 给 Scanner。
缓冲不是万能加速器,它把“系统调用开销”转化成了“内存占用 + 缓冲管理逻辑”。真正影响性能的,从来不是 bufio 本身,而是你有没有看清数据模式、调用节奏和资源边界。