Go 中的目录列表:包含代码示例的完整指南

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

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

开始课程

Go 中的目录列表:从简单到复杂

\n\n

文件系统操作是任何编程语言的基本任务之一。在 Go 中,它的实现如此优雅,以至于即使是像 list directory in Go 这样的常规操作也变成了一次引人入胜的探索。如果您曾经问过自己:“如何在 Go 中获取文件夹中的文件列表?”——那么您来对地方了。今天,我们将讨论所有可能的方法,从简单的输出到带过滤的递归遍历。

\n\n

为什么这个话题在 Stack Overflow 上如此受欢迎?因为 Go 提供了多种方法,选择正确的方法就成功了一半。我们将介绍经典的 os.ReadDir、已弃用的 ioutil.ReadDir(但在旧项目中仍可能遇到),以及用于递归遍历的强大 filepath.Walk。开始吧!

\n\n

1. 最简单的列表:os.ReadDir

\n\n

从 Go 1.16 开始,os 包新增了 ReadDir 方法,它已成为事实上的标准。它返回一个 os.DirEntry 对象的切片——这些是文件和文件夹的轻量级描述。如下所示:

\n\n
package main\n\nimport (\n    "fmt"\n    "os"\n    "log"\n)\n\nfunc main() {\n    // 读取当前目录的内容\n    entries, err := os.ReadDir(".")\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    fmt.Println("当前文件夹的内容:")\n    for _, entry := range entries {\n        fmt.Printf("- %s (目录: %v)\\n", entry.Name(), entry.IsDir())\n    }\n}\n
\n\n

这段代码将输出当前目录中的所有文件和文件夹。请注意:os.ReadDir 不会读取子文件夹——仅读取第一级。如果您需要递归地 list directory in Go,请继续阅读。

\n\n

2. ioutil.ReadDir:旧但熟悉

\n\n

在 Go 1.16 版本之前,所有人都使用 ioutil.ReadDir。它返回 []os.FileInfo——一个包含文件完整信息(大小、权限、修改时间)的更重结构。尽管该方法已被标记为 deprecated,您仍然可能在遗留代码中遇到它:

\n\n
package main\n\nimport (\n    "fmt"\n    "io/ioutil"\n    "log"\n)\n\nfunc main() {\n    files, err := ioutil.ReadDir("./mydir")\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    fmt.Println("mydir 中的文件(旧方法):")\n    for _, file := range files {\n        fmt.Printf("名称: %s, 大小: %d 字节\\n", file.Name(), file.Size())\n    }\n}\n
\n\n

主要区别:ioutil.ReadDir 按文件名对结果进行排序(类似于 ls),而 os.ReadDir 则不会。如果顺序很重要,请使用 sort.Slice 或手动排序。

\n\n

3. 使用 filepath.Walk 进行递归遍历

\n\n

当需要遍历所有子文件夹时,filepath.Walk 就派上用场了。此函数遍历目录树,为找到的每个元素调用回调函数。非常适合备份、文件搜索或项目结构分析:

\n\n
package main\n\nimport (\n    "fmt"\n    "os"\n    "path/filepath"\n)\n\nfunc main() {\n    root := "./myproject"\n    err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {\n        if err != nil {\n            return err\n        }\n        fmt.Printf("找到: %s (大小: %d)\\n", path, info.Size())\n        return nil\n    })\n    if err != nil {\n        fmt.Println("遍历错误:", err)\n    }\n}\n
\n\n

一个重要细节:filepath.Walk 会跟随符号链接,如果存在循环引用,可能会进入无限循环。对于生产环境,请使用 filepath.WalkDir(Go 1.16+)——它更轻量且更安全。

\n\n

4. 过滤:仅 .go 文件或仅文件夹

\n\n

通常不需要获取所有内容,而只需要特定类型的文件。让我们使用 strings.HasSuffix 和 IsDir() 检查来实现过滤

博客

书籍推荐