io.copy是go中流式二进制转换的核心,适用于加密、压缩等无损场景;需配合io.copybuffer优化慢设备吞吐,避免中间缓存,确保reader直达writer。

Go 里没有“大文件转换框架”这种东西,所谓流式转换,就是用 io.Copy、bufio.Scanner 或 encoding/csv 配合 context.Context 控制生命周期,每个环节不缓存整文件、不阻塞下游、不泄漏 goroutine。
用 io.Copy 做无损二进制流转换
适用于加密、压缩、加解密、格式封装(如 tar → zip 封装层)等不需要解析内容的场景。核心是避免中间分配,让数据从 reader 直达 writer。
- 直接传
os.File给io.Copy(dst, src)是安全的,它内部用 32KB 缓冲,但 NFS/云盘等慢设备建议显式用io.CopyBuffer(dst, src, make([]byte, 1024*1024))提升吞吐 - 若需在传输中插入逻辑(如计算 CRC、跳过 BOM),不能用
io.Copy,得换bufio.Reader+ 手动Read()循环 - 写入目标前务必检查
dst是否支持io.WriterAt(如需要断点续传),否则io.Copy无法恢复 - 别在
io.Copy后再调dst.Close()就完事——如果dst是*os.File,close 可能触发磁盘 flush 失败,要单独捕获错误
用 bufio.Scanner 做文本行级转换
日志过滤、CSV 字段重排、JSON Lines 格式清洗等典型场景。关键不是“怎么读”,而是“怎么不让内存涨上去”。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
- 默认单行上限 64KB,遇到含 base64 的日志会 panic,必须提前调
scanner.Buffer(make([]byte, 64*1024), 10*1024*1024)设最大长度 -
scanner.Text()返回的是底层缓冲区子切片,若存进 slice 或 map 长期持有,整个缓冲区无法 GC;要保存内容,改用strings.Clone(scanner.Text())或string(scanner.Bytes()) - 空行返回
[]string{},不是 error,别用if err != nil判断,而要用if len(record) == 0 - 每轮循环结束后必须检查
scanner.Err():EOF 是正常结束,但syscall.EPIPE或磁盘 I/O 错误必须中断 pipeline
用 encoding/csv + bufio.Reader 处理 CSV 流
GB 级 CSV 转 Parquet、字段脱敏、列筛选等。标准库的 csv.Reader 本身不流式,套一层 bufio.Reader 才真正可控。
- 必须用
bufio.NewReaderSize(f, 64*1024)包装文件,否则默认 4KB 缓冲会导致机械盘上 syscall 过多、卡顿 - Windows 导出的 CSV 常带 UTF-8 BOM,
csv.Reader不自动跳过,得手动读前三字节判断并丢弃 - 字段数不固定时,设
reader.FieldsPerRecord = -1,否则某行多一个逗号就报wrong number of fields并中断整个流 - 写入目标 CSV 时,
csv.Writer必须包bufio.Writer,且每写 1000 行主动w.Flush();等程序退出才 flush,panic 就丢数据
用 context.Context 控制 pipeline 生命周期
所有 stage 都是独立 goroutine,靠 channel 串起来,ctx.Done() 是唯一退出信号。没它,超时、取消、错误传播全失效。
- 每个 stage 必须启动 goroutine,不能同步调用;例如
go func() { defer close(out); for range in { ... } }() - 所有
select必须把ctx.Done()放第一顺位,否则可能卡在in 或 <code>out 上永远不响应 cancel - 输入 channel 类型应为
(只读),输出为 <code>chan(只写),编译器能防误写 - stage 内部禁止
close(in)——输入由上游控制;但必须defer close(out),否则下游range out永远阻塞
真正难的不是写对某一行代码,而是确保每个 stage 的 goroutine 在 ctx 被 cancel 后干净退出、channel 关闭时机精确、缓冲区大小匹配真实 IO 特性——这些细节不压测根本看不出问题。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










