推荐用 os.ReadDir 读单层目录(Go 1.16+ 替代 ioutil.ReadDir),高效轻量;递归遍历用 filepath.Walk,自动深度扫描并支持回调过滤;注意权限错误处理、隐藏文件判断及跨平台路径拼接。
使用 Go 语言遍历目录并读取文件列表,最常用且推荐的方式是 ioutil.ReadDir(Go 1.16+ 已弃用,应改用 os.ReadDir)或更底层的 filepath.Walk。下面直接讲清楚怎么用、该选哪个、注意什么。
os.ReadDir 是 Go 1.16 引入的轻量级替代方案,比旧版 ioutil.ReadDir 更高效,不加载完整文件信息(如内容),只读取目录项元数据。
[]fs.DirEntry,每个条目支持快速判断是否为目录或文件(.IsDir())sort.Slice
示例:
package main
import (
"fmt"
"os"
)
func main() {
entries, err := os.ReadDir("./mydir")
if err != nil {
panic(err)
}
for _, entry := range entries {
if entry.IsDir() {
fmt.Printf("DIR %s\n", entry.Name())
} else {
fmt.Printf("FILE %s\n", entry.Name())
}
}
}
当需要深度扫描子目录(比如查找所有 .go 文件),用 filepath.Walk 最直接。它自动递归,并对每个路径调用回调函数。
func(path string, info fs.FileInfo, err error) error
info.IsDir() 区分目录/文件;若为目录且想跳过其子项,可返回 filepath.SkipDir
示例:列出所有 .txt 文件路径
err := filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() && filepath.Ext(path) == ".txt" {
fmt.Println(path)
}
return nil
})
ioutil.ReadDir 在 Go 1.16+ 已被标记为 deprecated,新项目请统一用 os.ReadDir
os.ReadDir 和 filepath.Walk 都不会自动处理权限错误(如无读取权限的子目录),遇到时回调中 err != nil,需显式检查并决定是否继续. 开头),需手动判断 entry.Name()[0] == '.'(注意空名和 Windows 兼容性)filepath.Join,别用字符串 +,否则跨平台出错如果你常做类似操作,可以封装一个带错误处理和扩展名过滤的小工具:
func WalkFiles(root string, exts ...string) ([]string, error) {
var files []string
extSet := make(map[string]bool)
for _, e := range exts {
extSet[strings.ToLower(e)] = true
}
err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
if err != nil {
ret
urn nil // 忽略权限错误,继续遍历
}
if !info.IsDir() {
ext := strings.ToLower(filepath.Ext(path))
if len(exts) == 0 || extSet[ext] {
files = append(files, path)
}
}
return nil
})
return files, err
}
调用:goFiles, _ := WalkFiles("./src", ".go")
基本上就这些。不用第三方库,标准库已足够健壮。选 os.ReadDir 做单层,选 filepath.Walk 做递归,注意错误处理和路径安全,就稳了。