go中按固定大小写入文件本质是精确控制每次写入字节数上限,必须用io.copyn流式切分:源文件os.open打开、分片os.create零填充命名、自动处理eof和末块;禁用os.readfile(oom)、bufio.scanner(不可回退)和手动read(易丢字节);合并需数字排序+sha256校验。

Go 里按固定大小写入文件,本质是控制每次写入的字节数上限,不是靠“写满再关”或“等缓冲区溢出”。关键得用 io.CopyN,它不加载全文、不依赖行边界、不丢末尾字节——其他方式在 GB 级场景下要么 OOM,要么错位。
用 io.CopyN 流式切分大文件
这是唯一能精确控量又不爆内存的办法。它从 io.Reader(比如打开的源文件)往 io.Writer(比如新分片)拷贝指定字节数,自动处理 EOF 和最后一块不足的情况。
- 源文件必须用
os.Open打开,绝不能用os.ReadFile——1GB 文件直接 OOM - 目标分片用
os.Create(fmt.Sprintf("part_%03d", i))创建,零填充命名防排序错乱 - 每次调
io.CopyN(dst, src, chunkSize),返回值n就是实际写入字节数;n 或 <code>err == io.EOF就该停了 - 不用手动算剩余长度,也不用
src.Seek回退——io.CopyN内部已处理指针偏移
别碰 bufio.Scanner 或手动 Read 循环
这两类写法在按大小切分时几乎必然出问题:
-
bufio.Scanner是单向流,Scan()后无法回退指针,想从第 500MB 开始切第二块?只能重开文件再扫一遍,O(N²) 时间复杂度 - 手动
Read容易因缓冲区大小和文件长度不整除,导致末尾少读几字节,或误把n == 0当 EOF 而提前中断 -
bufio.Scanner默认 64KB 缓冲,遇到超长行(如含 base64 的 JSON)会 panic,且并发切分时易耗尽 fd
写入后必须校验顺序与完整性
按大小切分本身不保语义,但合并失败往往几个月后才暴露:
- 用
filepath.Glob("part_*")获取文件列表后,必须提取序号转int排序,不能直接sort.Strings——否则part_1、part_10、part_2错序 - 合并时用
os.Create新建目标文件,别用os.OpenFile(..., os.O_APPEND),避免并发或残留内容污染 - 每个分片打开后直接
io.Copy(merged, part),完成后Close();别用bytes.Buffer拼接——大分片会爆内存 - 分割前和合并后都用
sha256.Sum256+io.Copy流式计算哈希比对,os.Stat().Size()不足以验证内容一致
真正难的不是“怎么切”,而是“怎么确保切完还能原样拼回去”。零填充命名、严格顺序、流式哈希校验,这三步漏掉任何一环,数据就静默损坏了。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











