压缩比=原始数据字节长度÷压缩后字节长度,需将原始数据转为[]byte后用len()获取长度,压缩后必须调用Close()并从bytes.Buffer中取len(),二者相除即得比值。

怎么用 len() 和压缩前后字节对比算压缩比
压缩比就是原始数据大小除以压缩后大小,本质是两个 []byte 长度的比值。Go 里没有内置“压缩比函数”,但计算逻辑极简:先拿到原始数据长度,再用对应压缩器(如 gzip.Writer)压完,取结果缓冲区长度,相除即可。
注意别直接对字符串调 len()——那是 UTF-8 字节数,不是原始内容长度;应统一转成 []byte 后取 len()。
- 原始数据必须是
[]byte,避免隐式编码转换(比如string转[]byte是零拷贝,安全) - 压缩后数据必须从底层
bytes.Buffer或其他io.Writer中完整读出,不能只看Write()返回值 - 务必调用压缩器的
Close(),否则末尾校验和、压缩流尾部可能没写入,导致长度偏小、解压失败
compress/gzip 下的典型计算流程
以 compress/gzip 为例,这是最常用于网络包压缩的格式。关键点在于:压缩器本身不持有最终字节,它只是个写入器,你得把输出收集到 bytes.Buffer 才能测长度。
示例代码片段:
立即学习“go语言免费学习笔记(深入)”;
buf := &bytes.Buffer{}
gz := gzip.NewWriter(buf)
gz.Write([]byte("hello world")) // 原始数据
gz.Close() // 必须关闭!否则 buf.Len() 不准确
originalLen := 11
compressedLen := buf.Len()
ratio := float64(originalLen) / float64(compressedLen)
fmt.Printf("压缩比: %.2f:1\n", ratio)
这里 ratio 大于 1 表示有压缩效果;若小于或接近 1,说明数据本身难压缩(比如已加密、已压缩的二进制),继续压反而浪费 CPU。
为什么用 compress/zlib 算出来的比 gzip 高?
因为 zlib 封装更轻:没有 GZIP 的文件头、时间戳、操作系统标识等额外字段,纯 DEFLATE 流。同样内容下,zlib 输出通常比 gzip 少 10–20 字节,尤其在小包(
- HTTP/2 或 RPC 协议内嵌压缩,倾向用
compress/zlib(如 gorpc 的flate层) - 文件传输或日志归档,用
compress/gzip更通用,解压兼容性好 - 不要跨格式比较压缩比——
gzip的 header 开销是协议一部分,真实网络带宽节省要看总传输字节数,不是纯算法比值
容易被忽略的边界情况
压缩比不是越高压得越好,很多线上问题出在“盲目压缩小数据”上。
- 原始数据 gzip 压缩后可能反而更大(header 占比过高)
- 随机数据、加密密文、已压缩音视频帧,
gzip压缩比常为 0.95:1 甚至更低,此时压缩纯属增加 CPU 负担 - 用
gzip.NewWriterLevel(buf, gzip.NoCompression)测试 baseline,确认是否真有收益 - 生产环境建议加阈值判断:只对 >512 字节且疑似文本/JSON/XML 的 payload 启用压缩
真正影响网络性能的是“传输总字节数”,不是压缩比数字本身;而总字节数 = 压缩后长度 + 协议头开销 + 可能的 base64 编码膨胀。别只盯着一个比值做决策。


















