压缩比需手动计算为原始目录总大小÷压缩后zip文件大小;原始大小须用filepath.walk遍历并过滤符号链接和设备文件,zip大小必须在archive/zip.writer.close()后读取。

Go 语言本身不直接提供「压缩比」这个计算结果,它只负责生成压缩数据;压缩比必须由你手动计算:用原始目录总大小 ÷ 压缩后 ZIP 文件大小。关键难点不在公式,而在「原始大小怎么算准」和「ZIP 大小何时读取」——这两步错一点,压缩比就失真。
怎么准确获取源目录总字节数
不能靠 os.Stat().Size()(那只是单个文件),也不能简单递归加总却不跳过符号链接或设备文件。常见错误是把 /proc 或 /dev 下的伪文件也算进去,导致原始大小虚高。
- 用
filepath.Walk遍历,对每个os.FileInfo调用info.Size()前,先检查info.Mode()&os.ModeSymlink != 0(跳过软链)和info.Mode()&os.ModeDevice != 0(跳过块/字符设备) - 避免重复统计硬链接:可选地用
info.Sys().(*syscall.Stat_t).Ino和dev组合做 inode 去重(仅 Linux/macOS) - 注意:空目录不占磁盘空间,但也要计入遍历路径——否则后续 ZIP 中缺目录结构,解压后可能出错
ZIP 文件大小必须在 w.Close() 后读取
archive/zip.Writer 是流式写入,内部缓冲区 + 中央目录写入都发生在 w.Close() 时。如果在 w.Close() 前调用 os.Stat(),得到的往往是 0 或不完整大小。
- 务必在
defer w.Close()的对应位置之后,再打开 ZIP 文件并读取os.Stat().Size() - 不要用
bytes.Buffer.Len()代替文件大小——Buffer 可能被复用、截断,且未包含 ZIP 中央目录开销(约几百字节) - 若 ZIP 写入的是网络流(如 HTTP response body),则无法直接获取大小,此时压缩比不可算,需改用采样估算
压缩比数值本身容易误导,别只看一个数字
同一个目录,用 zip.DefaultCompression 和 zip.BestCompression 算出来的压缩比可能差 20%+,但实际耗时翻 3 倍。更麻烦的是:ZIP 格式本身有固定开销(每个文件至少 30 字节 header + central directory),小文件多的目录,压缩比天然偏低。
- 建议同时记录:文件总数、平均文件大小、最大单文件体积——这些比单纯一个「3.2:1」更有诊断价值
- 如果目录含大量已压缩文件(
.jpg、.mp4、.zip),实测压缩比常低于 1.05:1,这不是代码问题,是熵限制 - 别忘了磁盘块大小影响:1KB 文件在 ext4 上实际占 4KB,但
info.Size()返回 1024——原始大小按逻辑大小算,不是物理占用
真正难的不是算除法,而是确保分子分母都反映真实 I/O 成本:原始大小要剔除非数据项,ZIP 大小要等中央目录落盘。漏掉 w.Close() 或误把软链接当普通文件,压缩比数字再好看也没意义。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











