在 Go (Golang) 中处理 ZIP 归档:创建、读取和提取文件

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

在 Go (Golang) 中处理 ZIP 归档:完整指南



在现代 Go (Golang) 开发中,处理归档是一项常见任务。无论是打包日志、上传文件到服务器还是创建备份——标准库 archive/zip 提供了创建、读取和修改 ZIP 归档所需的一切,无需安装第三方依赖。在本文中,我们将通过实际示例介绍 Go 中 ZIP 的基本操作。



archive/zip 包的主要功能

archive/zip 包是 Go 标准库的一部分,支持:

  • 创建具有任意文件夹结构的新 ZIP 归档
  • 读取现有归档的内容
  • 提取单个文件或整个归档
  • 向现有归档添加文件(通过复制)
  • 处理文件元数据(日期、权限、注释)
  • 流式处理(无需将整个归档加载到内存中)


在 Go 中创建 ZIP 归档

要创建归档,使用 zip.NewWriter(),它接受一个 io.Writer。这允许将归档写入文件或缓冲区(例如,用于通过 HTTP 发送)。



package main

import ( "archive/zip" "bytes" "fmt" "io" "log" "os")

func createZip() { // 为归档创建缓冲区 buf := new(bytes.Buffer) writer := zip.NewWriter(buf)

// 添加一个包含文本的文件 file1, err := writer.Create("hello.txt") if err != nil { log.Fatal(err) } _, err = file1.Write([]byte("你好,世界!这是来自 ZIP 归档的文件。")) if err != nil { log.Fatal(err) }

// 在子文件夹中添加文件 file2, err := writer.Create("docs/readme.md") if err != nil { log.Fatal(err) } _, err = file2.Write([]byte("# 文档readme 的内容。")) if err != nil { log.Fatal(err) }

// 必须关闭 writer err = writer.Close() if err != nil { log.Fatal(err) }

// 将归档保存到文件 err = os.WriteFile("example.zip", buf.Bytes(), 0644) if err != nil { log.Fatal(err) } fmt.Println("归档已创建:example.zip")}

func main() { createZip()}


从 ZIP 中读取和提取文件

要读取归档,使用 zip.OpenReader() 或 zip.NewReader()(用于内存中的数据)。每个文件由 zip.File 结构表示。



func readZip() {    reader, err := zip.OpenReader("example.zip")    if err != nil {        log.Fatal(err)    }    defer reader.Close()

for _, f := range reader.File { fmt.Printf("文件:%s(大小:%d 字节)", f.Name, f.UncompressedSize64)

// 打开文件内容 rc, err := f.Open() if err != nil { log.Fatal(err) }

// 读取内容 content, err := io.ReadAll(rc) if err != nil { log.Fatal(err) } rc.Close()

fmt.Printf("内容:%s

", content) }}


将所有文件提取到磁盘

通常需要将归档解压到指定目录。此时正确创建子文件夹很重要。



func extractZip(src, dest string) {    reader, err := zip.OpenReader(src)    if err != nil {        log.Fatal(err)    }    defer reader.Close()

for _, f := range reader.File { // 提取路径 fpath := filepath.Join(dest, f.Name)

// 检查路径是否超出 dest 范围(安全性) if !strings.HasPrefix(fpath, filepath.Clean(dest)+string(os.PathSeparator)) { log.Fatalf("无效路径:%s", fpath) }

// 创建文件夹 if f.FileInfo

推荐