实测压缩率zstd≈gzip>lzw,速度zstd最快(压缩快2–5倍、解压快3–8倍),lzw虽快但压缩率仅gzip的60–70%且不支持流式调节;推荐klauspost/compress实现zstd,避免CGO和过时API。

Go 里 gzip、zstd 和 lzw 压缩率与速度到底差多少
实测下来,压缩率排序是 zstd ≈ gzip > lzw,但速度差异极大:zstd(中高阶设置)压缩比 gzip 快 2–5 倍,解压快 3–8 倍;lzw 虽然极快,但压缩率通常只有 gzip 的 60–70%,且不支持流式压缩参数调节。
gzip默认用gzip.BestSpeed(等级 1)时,压缩慢于zstd,但解压略稳;设为gzip.BestCompression(等级 9)后,CPU 占用飙升,收益却很有限(文本类数据再压也难超 5% 提升)zstd的ZSTD_DEFAULT_CLEVEL(等级 3)已明显快于gzip等级 6,且压缩率不输;等级 1–3 是大多数服务的甜点区间lzw在compress/lzw包里只支持LitWidth(字典位宽)调整,无法控制压缩深度或内存用量,对 JSON/日志等重复结构少的数据几乎无效
Go 标准库没 zstd,得用第三方包——选哪个才靠谱
github.com/klauspost/compress 是当前最稳定的 zstd Go 实现,API 清晰、panic 少、支持流式和 bytes 模式;它不依赖 CGO,静态编译无坑。而 github.com/DataDog/zstd 虽然性能略高,但默认启用了 CGO,交叉编译失败率高,CI 构建容易卡住。
- 用
klauspost/compress时,直接调zstd.NewWriter即可,传&zstd.EncoderOptions{Level: 3}控制强度 - 别用
zstd.NewWriterLevel(旧 API),它已被标记为 deprecated,新版本会删 - 如果项目已用
golang.org/x/exp,注意:其中的实验性zstd实现未维护,不建议上线使用
lzw 解压失败常见于 EOF 或 magic number 不匹配
compress/lzw 对输入极其敏感:它不校验 header,也不检查数据完整性,一旦源数据不是由同个 LitWidth 写入的,reader.Read 很可能在中间就返回 io.ErrUnexpectedEOF 或静默截断。
- 写入和读取必须用完全相同的
lzw.Order(LSB或MSB)和LitWidth(通常 8–12),错一个就解不开 - HTTP 传输
lzw数据时,别依赖Content-Encoding: x-lzw—— 浏览器和多数代理根本不识别,连 gzip 都不认,更别说这个 - 日志归档场景下,
lzw的随机访问支持为零,想跳转解压某一段?做不到
什么时候该坚持用 gzip,而不是换 zstd
如果你的服务要和老系统、嵌入式设备或某些 CDN(比如部分 Nginx 配置)对接,且对方只实现了 RFC 1952 的 gzip,那就别强行上 zstd——不是技术不行,是生态不兼容。
- Nginx 默认只解
gzip,开zstd需要额外模块(ngx_http_zstd_filter_module),很多运维不会配,也不敢上线 - Go 的
net/http客户端默认不发Accept-Encoding: zstd,服务端即使支持,客户端也可能忽略响应头里的Content-Encoding: zstd gzip的Reader支持Seek(配合gzip.NewReader+io.Seeker),zstd目前所有 Go 实现都不支持,想做分块解压或断点续解,只能自己缓存整段
zstd 的优势在可控场景里很明显,但只要链路里有一环不支持,就得退回来——压缩算法从来不是纯性能题,是协作边界题。