压缩比本质是原始数据与压缩后数据字节长度的比值,公式为float64(len(original))/float64(len(compressed));值越大压缩效果越好,1.0表示无压缩,小于1.0属异常;使用gzip需调用close()并用buf.bytes()获取完整压缩流,否则比值虚高;不同算法(如zstd、zlib、gzip)压缩比差异显著,短数据可能压缩后反而更大。

压缩比计算的本质是字节长度对比
压缩比不是Go标准库直接提供的指标,而是你对原始数据和压缩后数据的len()做除法得到的比值。核心公式就是:float64(len(original)) / float64(len(compressed))。注意:这个值越大,说明压缩效果越好;1.0 表示没压缩,小于 1.0 是异常(比如压缩格式加了大量元数据或输入太短)。
用gzip压缩后立刻算压缩比的典型流程
Go里最常用的是compress/gzip,但容易忽略两点:一是gzip.Writer必须Close()才能写出完整流;二是压缩结果要从bytes.Buffer中读取最终字节,不能只看写入过程中的临时长度。
- 先用
bytes.NewBuffer(nil)创建目标缓冲区 - 传给
gzip.NewWriter(),再Write()原始字节 - 务必调用
gzw.Close()—— 否则尾部校验和、长度信息缺失,压缩不完整,算出来的比值偏高(即虚高) - 用
buf.Bytes()获取最终压缩数据,再套公式
buf := bytes.NewBuffer(nil)
gzw := gzip.NewWriter(buf)
gzw.Write([]byte("hello world hello world"))
gzw.Close() // 关键!不能漏
ratio := float64(len("hello world hello world")) / float64(len(buf.Bytes()))
不同压缩算法对压缩比的影响不可忽略
compress/zlib、compress/zstd(需第三方库如github.com/klauspost/compress/zstd)在相同输入下会给出明显不同的压缩比。zstd 通常比 gzip 在中等长度文本上高 10–20%,但启动开销略大;zlib 默认兼容性更好,但压缩率常略低于 gzip。
- 不要假设“用了压缩就一定有收益”——比如压缩一个 12 字节字符串,gzip 输出可能达 30+ 字节(头+校验+填充),压缩比反而
- 小数据建议加阈值判断,例如
if len(data) ,避免负优化 - 如果需要稳定高压缩比,考虑用
zstd.WithEncoderLevel(zstd.SpeedBetterCompression)显式设等级
常见错误:把Write()返回值当压缩后长度
gzip.Writer.Write()返回的是写入的原始字节数(和输入一致),不是压缩后长度。有人误用n, _ := gzw.Write(data); ratio = float64(len(data)) / float64(n),这算出来永远是 1.0,完全无效。
- 压缩后长度只能从底层
io.Writer(如bytes.Buffer)中获取 - 别依赖
gzw自身提供长度方法 —— 它没有 - 如果用
io.Pipe或网络流,必须等整个流结束并Close()后才能拿到总长度
Close()、误读Write()返回值、或者对极短输入不做防护,都会让数字完全失真。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











