go文件i/o优化关键在复用句柄、调优缓冲、避免冗余系统调用:日志追加应复用*os.file并调整bufio.writer至64kb~1mb,大文件优先用io.readfull+预分配切片,小文件遍历用filepath.walkdir减少stat开销。
Go 的文件 I/O 默认性能不差,但高频小文件读写、日志追加、大文件处理等场景下,os.Open + bufio.NewReader 或直接 io.Copy 往往不是最优解——关键在缓冲策略、系统调用频次和内存复用。
避免每次读写都新建 os.File 和 bufio.Reader/Writer
频繁打开关闭文件(如每条日志都 os.OpenFile(..., os.O_WRONLY|os.O_APPEND))会触发大量系统调用,且 bufio 的默认 4KB 缓冲区在小数据量时反而增加拷贝开销。
- 长期服务中应复用
*os.File句柄,用file.Seek(0, io.SeekEnd)替代反复OpenFile追加 -
bufio.Writer的缓冲大小需按写入粒度调整:日志场景用 64KB~1MB;配置文件解析可降到 2KB - 复用
bufio.Writer时务必调用w.Flush(),否则数据滞留在缓冲区——这是最常被忽略的丢数据原因
大文件读取优先用 io.ReadFull + 预分配切片,而非 bufio.Scanner
bufio.Scanner 默认按行切割,内部不断 append 切片并扩容,对 GB 级二进制或固定格式文件(如 Protocol Buffers 分块)会造成显著 GC 压力和内存碎片。
- 已知大小的文件,用
make([]byte, size)预分配,配合io.ReadFull(file, buf)一次性读满 - 流式大文件(如视频分片),改用
file.Read(buf)+ 手动处理返回的n, err,跳过bufio的额外状态管理 - 注意:Linux 下
read(2)系统调用在普通磁盘上通常一次最多读 128KB,预分配过大无意义,1MB 是较稳妥上限
启用 O_DIRECT(仅 Linux)绕过内核页缓存,但必须满足对齐约束
当业务明确需要“绕过 Page Cache 直写磁盘”(如数据库 WAL 写入),可尝试 syscall.O_DIRECT,但 Go 标准库不直接支持,需用 syscall.Open 并手动对齐内存与文件偏移。