gzip.Writer必须调用Close(),否则缺失CRC32校验值和ISIZE字段导致解压失败;zlib.Writer无需Close()但需Flush(),因gzip含元数据而zlib更轻量。

gzip 和 zlib 都能压单个文件流,但 gzip 带元数据(如修改时间、文件名),zlib 不带——传给 HTTP 或存档用 gzip,嵌入协议或做底层流压缩用 zlib。
gzip.Writer 必须调用 Close(),否则解压失败
不关 gzip.Writer,尾部的 CRC32 校验码和 ISIZE 字段就写不进去。用 gunzip -t 检查会报 unexpected end of file;Go 里用 gzip.NewReader 解压时也可能 panic 或读出零字节。
- 哪怕只写了一小段数据,也得显式调用
gzWriter.Close() -
defer gzWriter.Close()是最安全的习惯,别依赖defer outputFile.Close()代替 - 如果写入中途出错,要先
gzWriter.Close()再 return,避免资源泄漏
zlib.Writer 不需要 Close(),但必须 Flush()
compress/zlib 的设计更轻量:它不写头部元信息,也不强制要求尾部校验块。所以没有 Close() 方法,但如果你希望立刻把缓冲区内容写出(比如网络传输中需低延迟),得手动 zlibWriter.Flush()。
- 不
Flush()也可能正常解压,但接收方可能卡在等待更多数据 - 大文件流式压缩时,每写入几 MB 就
Flush()一次,能减少端到端延迟 -
zlib.NewWriterLevel(&buf, zlib.BestSpeed)支持指定压缩级别,范围同gzip(1–9)
gzip 与 zlib 解压都必须用 NewReader 包一层
不能直接 os.Open("x.gz") 后拿 *os.File 去 io.Copy(dst, src)——那只是复制二进制流,不是解压。必须先用对应 Reader 封装,再交给 io.Copy。
立即学习“go语言免费学习笔记(深入)”;
- gzip 解压:
gzip.NewReader(file)→io.Copy(dst, gr)→gr.Close() - zlib 解压:
zlib.NewReader(file)→io.Copy(dst, zr)→zr.Close() -
gr.Close()和zr.Close()释放内部 reader 资源,虽不严格必需,但建议加
压缩级别选错会导致 CPU 白烧或体积白大
默认 gzip.DefaultCompression(-1)是平衡点;gzip.NoCompression(0)只是套壳,体积几乎不变;gzip.BestCompression(9)CPU 占用翻倍,但对已压缩过的数据(如 JPEG、MP4)几乎没收益。
- 日志归档、实时响应:用
gzip.BestSpeed(1) - 备份文件、离线传输:用
gzip.BestCompression(9),但先确认源文件是否可压(文本/JSON/YAML 可,视频/音频不可) - zlib 级别命名一致,但实际压缩率略低于 gzip(因无头信息优化)
真正容易被忽略的是:gzip 和 zlib 都只处理「流」,它们根本不关心「文件」——路径、权限、目录结构全得你手动组织。想打包多文件?必须上 archive/zip 或 archive/tar + compress/gzip 嵌套,顺序错了(比如先 gzip 再 tar)就只能得到乱码。


















