推荐使用流式读写处理大文件,通过bufio缓冲分块读取避免内存溢出,按行处理可用Scanner,大块读取用固定buffer,随机访问可选mmap,注意缓冲区大小、资源释放与对象复用,结合场景平衡性能与内存。

处理大文件I/O时,Golang推荐使用流式读取和写入的方式,避免一次性将整个文件加载到内存中。核心思路是通过缓冲分块读写,结合适当的系统调用和内存管理,保证程序的性能和稳定性。
使用 bufio 进行缓冲读写
对于大文件,直接使用 os.Open 和 bufio.Reader/Writer 能有效减少系统调用次数,提升I/O效率。
示例:按行读取大文本文件
file, err := os.Open("large.log")
if err != nil {
log.Fatal(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
// 处理每一行
processLine(line)
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
注意:如果单行内容也很大,建议改用固定大小的 buffer 读取,防止内存溢出。
立即学习“go语言免费学习笔记(深入)”;
分块读取(Chunked Reading)
当不需要按行处理时,可使用固定大小的字节块进行读取,适用于二进制文件或日志合并等场景。
buffer := make([]byte, 64*1024) // 64KB 缓冲区
for {
n, err := reader.Read(buffer)
if n > 0 {
// 处理 buffer[0:n]
writeChunk(buffer[:n])
}
if err == io.EOF {
break
}
if err != nil {
log.Fatal(err)
}
}
这种方式控制内存使用量,适合GB级以上文件处理。
使用 mmap 提升随机访问性能
在某些需要频繁随机访问大文件的场景下,可以使用内存映射(mmap),但需注意平台兼容性。
Go标准库不直接支持 mmap,可通过 golang.org/x/sys/unix 调用:
data, err := unix.Mmap(int(fd), 0, length, unix.PROT_READ, unix.MAP_SHARED)
if err != nil {
log.Fatal(err)
}
// 使用 data 作为 []byte 访问文件内容
// 结束后记得 Munmap(data)
mmap 适合只读或小范围修改的场景,避免大量页面换出影响性能。
优化建议与注意事项
- 设置合理的缓冲区大小(如 32KB~1MB),太小降低效率,太大浪费内存
- 及时关闭文件句柄,使用 defer 防止泄露
- 避免在循环中创建大量临时对象,考虑 sync.Pool 复用 buffer
- 对极大数据,可结合 goroutine 做流水线处理,但注意磁盘顺序读写优势
- 在高并发写入时,使用 bufio.Writer 减少 sync 调用










