空文件压缩后体积变大是预期行为,因gzip最小输出20字节、zstd约14字节;计算压缩比前须拦截空数据,避免除零错误,并建议对小于512字节的数据跳过压缩。

空文件压缩后体积变大?这是预期行为,不是 bug
空文件(len(data) == 0)经 gzip 或 zstd 压缩后体积必然大于 0——因为所有主流压缩格式都带固定 header 和 trailer。比如 gzip 最小输出是 20 字节(10 字节 header + 8 字节 footer + 2 字节校验),zstd 是 14 字节左右。所以「压缩比 > 1」(即压缩后更大)对空数据完全正常。
计算压缩比前必须加空数据守门逻辑
直接用 len(compressed) / len(original) 算空文件会得到 NaN 或 panic(除零),更危险的是掩盖真实问题。正确做法是在压缩函数入口强制拦截:
- 检查
len(data) == 0,直接返回原切片或预设空压缩结果(如[]byte{}),不进压缩流程 - 加阈值守门:只对
len(data) >= 512的数据走压缩,小数据(尤其是 - 若业务要求“统一走压缩通道”,则在比值计算前加 guard:
if len(original) == 0 { return 0 },避免除零
gzip 压缩空字节流时的典型错误现象
你可能看到这些表现,其实都指向同一个根源:
-
gzip: invalid header:解压端收到空输入(len(data) == 0),但没做判空就传给gzip.NewReader - 压缩后文件无法用系统
gunzip解开:没调gzipWriter.Close(),导致 footer 缺失,实际输出只有 header - 同一份空数据反复压缩,每次输出长度不一致:复用了
bytes.Buffer且没Reset(),残留旧数据污染输出
真实项目里最容易被忽略的点
不是算法选错,而是边界没兜住。空数据、极小数据、已加密/已压缩字段(如 base64 图片、AES 密文)再套一层 gzip,只会白耗 CPU。生产环境建议把守门逻辑下沉到统一的 Compressor 接口实现里,而不是每个调用点重复写 if len(data) ——否则三个月后新加的 RPC 接口大概率漏掉这一行。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











