
用 crypto/sha256 计算文件哈希值,别直接读整个文件进内存
大文件(比如几百 MB 的镜像)用 ioutil.ReadFile 或 os.ReadFile 会瞬间吃光内存,程序可能被系统 OOM kill。正确做法是流式读取,边读边喂给哈希器。
- 用
os.Open打开文件,得到*os.File - 创建
sha256.New()实例,它实现了io.Writer - 调用
io.Copy(hasher, file)—— 这是最简洁安全的流式计算方式 - 最后用
hasher.Sum(nil)拿到结果,fmt.Sprintf("%x", sum)转成十六进制字符串
校验失败?先确认你比对的是同一份哈希(字节 vs 字符串、大小写、换行)
常见错误不是算法写错,而是比对环节出问题:比如把 hex 字符串当字节数组比,或服务端返回的 SHA256 带了前缀 sha256:,又或者 Windows 下文件末尾多了 \r\n 导致哈希不一致。
- 校验时统一用
strings.TrimSpace()清掉两端空白和换行 - 用
strings.ToLower()统一小写再比对,避免大小写混淆 - 如果对方提供的是 base64 编码的哈希(如 HTTP
digest头),要用base64.StdEncoding.DecodeString()先解码成原始字节,再跟hasher.Sum(nil)结果比较 - 不要用
==直接比两个[]byte,用bytes.Equal(a, b)防止时间侧信道攻击(尤其在 Web API 校验场景)
crypto/sha256 和 crypto/sha512 性能差多少?选哪个更合适
SHA256 在大多数现代 CPU 上比 SHA512 更快,尤其在小文件或高并发 I/O 场景下。SHA512 吞吐量理论上更高,但实际受限于内存带宽和 Go runtime 的缓冲策略,反而常慢 10%–20%。
- 除非你明确需要更强抗碰撞性(比如证书签名),否则默认选
sha256 - 注意
sha512输出长度是 64 字节,而sha256是 32 字节,路径、数据库字段、HTTP 头长度都要跟着调整 - Go 标准库里两者 API 完全一致,替换只需改 import 和构造函数名,无逻辑修改成本
多文件批量校验时,别为每个文件重复 new hasher
每次调用 sha256.New() 都会分配新结构体,高频调用(比如校验上千个小文件)会产生 GC 压力。可以复用 hasher 实例,但必须在每次计算前调用 Reset()。
立即学习“go语言免费学习笔记(深入)”;
- 错误写法:
hasher := sha256.New(); for _, f := range files { ... io.Copy(hasher, f) }—— 第二个文件哈希是累加的,不是独立的 - 正确写法:
hasher := sha256.New(); for _, f := range files { hasher.Reset(); io.Copy(hasher, f); sum := hasher.Sum(nil); ... } - 如果文件数量极大且并发校验,建议每个 goroutine 自己 new 一个 hasher,避免
Reset()的锁竞争(sha256.digest不是完全无锁的)










