Go中使用archive/zip包可直接创建和解压ZIP文件:创建需手动遍历目录、规范路径分隔符并调用zw.Close();解压须校验路径防穿越;内存操作可用bytes.Buffer;注意UTF-8文件名、权限设置及缓冲优化。

在 Go 中使用 archive/zip 包创建和解压 ZIP 文件非常直接,无需第三方依赖。核心在于理解 ZIP 是“写入器 + 文件头 + 数据流”的组合,解压则是遍历文件条目并逐个提取内容。
创建 ZIP 包(压缩多个文件或目录)
Go 的 zip.Writer 不支持直接递归压缩整个目录,需手动遍历路径、构造正确的内部路径(用斜杠分隔,不能用系统路径分隔符),再调用 zw.Create() 或 zw.CreateHeader() 写入条目。
- 先创建一个可写的文件(如
os.Create("out.zip")),再用它初始化zip.NewWriter() - 对每个待压缩的文件,用
filepath.Walk遍历;对每个文件,计算其在 ZIP 中的相对路径(例如src/a.txt→a.txt或sub/a.txt),注意把\替换为/ - 调用
zw.Create(filePathInZip)得到一个io.Writer,再把源文件内容拷贝进去(io.Copy(writer, file)) - 最后别忘了调用
zw.Close()—— 它会写入中央目录,缺了这步 ZIP 文件无法被正常识别
解压 ZIP 包(提取所有文件到指定目录)
解压的关键是安全处理路径:防止路径穿越(如 ../../../etc/passwd)和确保目标路径在允许范围内。
- 用
zip.OpenReader("in.zip")打开 ZIP,遍历r.File切片 - 对每个
*zip.File,先检查file.FileInfo().IsDir()判断是否为目录;若是,用os.MkdirAll()创建对应目录(路径中仍需将/转为系统分隔符) - 若为文件,先校验路径是否越界(例如用
strings.HasPrefix(filepath.Clean(path), filepath.Clean(targetDir))),再打开输出文件(os.Create()),然后从file.Open()读取并写入 - 记得关闭每个打开的
file.Open()返回的ReadCloser
处理单个文件或内存中的 ZIP(无磁盘 IO)
如果只是临时打包几个字节或从内存解压,可用 bytes.Buffer 替代文件句柄。
立即学习“go语言免费学习笔记(深入)”;
- 压缩:创建
buf := &bytes.Buffer{},传给zip.NewWriter(buf),写完后buf.Bytes()就是 ZIP 二进制数据 - 解压:用
zip.NewReader(bytes.NewReader(data), int64(len(data)))直接从字节切片构建*zip.ReadCloser,后续逻辑一致 - 适合 Web API 返回 ZIP 下载、测试场景或配置打包等轻量需求
常见坑与注意事项
很多问题不是语法错误,而是语义或平台细节导致的:










