dan*_*neu 12

这是使用 Go 的内置递归文件遍历器的解决方案,因为到目前为止最佳答案已经实现了它们自己的文件遍历器:


另外,我今天在生成 zip 文件时发现的一些发现可能会让其他人头疼:

w.Create(zippath)w.Create("manifest.xml")w.Create("a/b/c.css)filepath.WalkReadDir

package main

import (
    "archive/zip"
    "fmt"
    "io"
    "os"
    "path/filepath"
)

// Zips "./input" into "./output.zip"
func main() {
    file, err := os.Create("output.zip")
    if err != nil {
        panic(err)
    }
    defer file.Close()

    w := zip.NewWriter(file)
    defer w.Close()

    walker := func(path string, info os.FileInfo, err error) error {
        fmt.Printf("Crawling: %#v\n", path)
        if err != nil {
            return err
        }
        if info.IsDir() {
            return nil
        }
        file, err := os.Open(path)
        if err != nil {
            return err
        }
        defer file.Close()

        // Ensure that `path` is not absolute; it should not start with "/".
        // This snippet happens to work because I don't use 
        // absolute paths, but ensure your real-world code 
        // transforms path into a zip-root relative path.
        f, err := w.Create(path)
        if err != nil {
            return err
        }

        _, err = io.Copy(f, file)
        if err != nil {
            return err
        }

        return nil
    }
    err = filepath.Walk("input", walker)
    if err != nil {
        panic(err)
    }
}
  • 无需先读再写。只做 io.Copy(dst, src) 所以目前 io.Copy(f, file) 你也关闭 w 两次,这不是一个错误,但 zip.Close 不会关闭底层资源和目标文件在程序的开头没有被关闭。所以目前可能会出现问题。程序也不完整(没有包规范,没有导入规范等) (3认同)
  • (作为记录,我的回答确实包括了@mh-cbon 的所有建议,iirc。谢谢。) (2认同)