直接用io.copy配合io.multiwriter将数据同时写入文件和sha256.new()哈希器,可边下载边计算sha256,避免oom且校验可信;需检查seek返回值、禁用os.o_trunc、正确调用hasher.sum(nil)并用hex.encodetostring转十六进制。

直接用 io.Copy 把数据同时写入文件和哈希器,就能在写入过程中同步算出 SHA256,无需等写完再读一遍——这是最省内存、也最不容易出错的方式。
用 io.MultiWriter 同时写入文件和 sha256.New()
Go 的 hash.Hash 接口实现了 io.Writer,所以能和文件句柄一起塞进 io.MultiWriter。只要一次 io.Copy,数据流过去,文件落盘、哈希更新就全完成了。
- 别手动
Read+Write+hasher.Write():既冗余,又容易漏写或长度错位 - 别等整个响应体读成
[]byte再写入:GB 级文件会直接 OOM -
hasher := sha256.New()必须在io.Copy前创建,且不能复用(除非显式hasher.Reset()) - 示例关键行:
io.Copy(io.MultiWriter(file, hasher), resp.Body)
断点续传场景下必须检查 Seek 返回值
如果文件已存在,你要从某个 offset 续传,得先 file.Seek(offset, io.SeekStart)。但这个操作不是“保证成功”的——它可能返回小于 offset 的值,说明文件被截断、覆盖或并发修改过。
- 必须检查
actual, err := file.Seek(offset, io.SeekStart),且actual != offset时应中止写入 - 错误类型可能是
*os.PathError或io.ErrUnexpectedEOF,不能只看err != nil -
os.O_CREATE | os.O_WRONLY是唯一安全的打开方式;千万别加os.O_TRUNC,否则续传前就把文件清空了
sha256.Sum256 和 sha256.New() 别混用
sha256.Sum256 是个值类型,适合一次性小数据哈希;sha256.New() 才是真正的流式哈希器。写入文件这种场景,只能用后者。
- 误用
sha256.Sum256([]byte(data)):它不维护状态,无法接收分块输入,结果和文件内容无关 - 调用
hasher.Sum(nil)才得到最终哈希值;写成hasher.Sum([]byte{})会多拼一个空切片,结果长度变长、校验失败 - 最终转十六进制用
hex.EncodeToString(hasher.Sum(nil)),不是fmt.Sprintf("%x", ...)—— 后者对[]byte输出带空格
真正难的不是怎么写,而是怎么判断“这次写入是否可信”:偏移是否一致、目标文件是否被外部修改、哈希器是否中途重置过——这些边界条件一旦漏掉,校验就形同虚设。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











