snappy包不属于Go标准库compress/,必须用go get github.com/golang/snappy安装并import "github.com/golang/snappy";其Encode返回新[]byte,需用[:len(dst)]截取有效数据,支持缓冲复用以减少GC。

snappy 包不自带 compress/snappy,得用 github.com/golang/snappy
Go 标准库没有 compress/snappy —— 这是个常见误解。官方 compress/ 下只有 gzip、zlib、bzip2 等,snappy 是第三方实现,主流是 github.com/golang/snappy(由 Go 团队维护,非社区 fork)。直接 go get compress/snappy 会失败。
正确安装方式:
go get github.com/golang/snappy
导入时写:
import "github.com/golang/snappy"
- 别名导入不是必须,但若项目里同时用多个压缩包(比如
zstd和snappy),建议加短名避免冲突:snappy "github.com/golang/snappy" - 这个包是纯 Go 实现,无 CGO 依赖,跨平台编译友好;但性能略低于 C 版本(如
google/snappy的 cgo 绑定),小数据量差异不大,大数据量可实测对比
压缩:用 snappy.Encode,注意输出 slice 容量可能大于实际长度
snappy.Encode 不会原地压缩,而是返回一个新 []byte,其 len 是压缩后真实长度,但 cap 可能更大(内部复用缓冲池)。如果后续要序列化或网络传输,务必用 out[:len(out)] 截取有效部分,否则可能多传几十字节垃圾数据。
典型用法:
src := []byte("hello world")
dst := snappy.Encode(nil, src) // 第一个参数可为 nil,也可复用切片
// ✅ 正确使用压缩结果
compressed := dst[:len(dst)]
- 复用
dst切片能减少 GC 压力:buf := make([]byte, 0, 1024),然后每次调snappy.Encode(buf[:0], src) -
snappy.Encode对短数据("a" 得到 7 字节;这不是 bug,是 Snappy 算法特性,适合 ≥100B 的 payload - 不支持流式压缩(如
io.Writer接口),如需流式,得自己封装或换用github.com/klauspost/compress/snappy
解压:用 snappy.Decode,必须预估最大解压尺寸或用 snappy.DecodedLen
snappy.Decode 需要目标切片有足够容量,否则 panic:panic: snappy: corrupt input(实际是越界写,错误信息误导性很强)。安全做法是先调 snappy.DecodedLen 获取理论最大长度,再分配空间。
dst := make([]byte, snappy.DecodedLen(src))
decoded, err := snappy.Decode(dst, src)
if err != nil {
// 处理 err,可能是损坏数据或 dst 不够大
}
// decoded == dst[:n],即有效解压内容
-
snappy.DecodedLen返回的是「上界」,实际解压长度 ≤ 返回值;分配刚好大小的切片最省内存 - 如果完全无法预估原始大小(如接收不受控的网络包),可用
snappy.MaxEncodedLen(n)反推:Snappy 编码后长度 ≤snappy.MaxEncodedLen(len(original)),但解压端没对应反向函数,此时建议加协议头存原始长度 - 解压失败常见原因:输入被截断、中间字节翻转、用了非 Snappy 编码的数据(比如误把 gzip 数据喂给
snappy.Decode)
性能关键:小数据别硬套 Snappy,优先考虑内存拷贝开销
Snappy 的设计目标是「快」而非「高压缩率」,但它仍有启动成本。对 copy() 在小 slice 上极快(底层用 memmove 优化)。
- 实测参考(i7-11800H,Go 1.22):
• 100B 数据:snappy 编解耗时 ≈ 300ns,copy≈ 5ns
• 10KB 数据:snappy ≈ 1.2μs,copy≈ 50ns
• 1MB 数据:snappy ≈ 0.8ms,copy≈ 0.1ms - 真正受益场景:RPC body、日志批量写入、列存格式(如 Parquet)中的单列数据,这些通常是几 KB 到几 MB 的连续块
- 别在 hot path 上对每个字段单独压缩(比如 struct 成员级 snappy),合并成 buffer 再压更划算
压缩率和速度的平衡点因数据而异,上线前务必用真实业务数据做 benchmark,而不是依赖文档里的“平均提升 3x”这种说法。

















