filepath.glob仅支持shell通配符,不支持正则;需正则匹配应使用filepath.walkdir配合regexp.matchstring,注意路径分隔符、大小写及相对路径处理。

Go 里用 filepath.Glob 做基础通配,但不支持正则
Go 标准库的 filepath.Glob 只支持 shell 风格通配符(*、?、[...]),不是正则表达式。想用 ^src/.*.go$ 这类正则?它直接 panic 或返回空切片。
常见错误现象:filepath.Glob("src/.*\.go") 匹配不到任何文件,因为 . 和 \ 在 glob 中无特殊含义,.* 被当字面量处理。
- 适用场景:快速匹配简单模式,如
"**/*.go"(注意:标准Glob不支持**,需用filepath.WalkDir+ 手动判断) - 若路径含中文或特殊符号,
Glob在 Windows/macOS 下行为基本一致,但大小写敏感性取决于文件系统 - 性能上比遍历后正则快不了多少——它底层也是遍历目录,只是过滤逻辑更轻量
真正做正则匹配得靠 filepath.WalkDir + regexp.MatchString
这是最灵活也最常用的方式:遍历路径,对每个 entry.Name() 或完整 entry.Path 执行正则判断。
示例:查找所有以 test_ 开头、在 internal/ 子目录下的 Go 测试文件:
re := regexp.MustCompile(`^internal/.*?/test_.*.go$`)
err := filepath.WalkDir(".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if !d.IsDir() && re.MatchString(path) {
fmt.Println(path)
}
return nil
})
- 注意用
path(完整路径)而非d.Name()(仅文件名),否则无法匹配目录层级 - Windows 下路径分隔符是
,建议统一用filepath.ToSlash(path)转成/再正则,避免写两套 pattern - 如果只关心文件名(比如“所有以
util结尾的 .go 文件”),用re.MatchString(d.Name())更安全,避免路径干扰
doublestar.Glob 支持 **,但依然不是正则
第三方库 github.com/bmatcuk/doublestar 补全了 ** 递归匹配能力,比如 doublestar.Glob("**/cmd/*/main.go") 能命中多层嵌套,但它仍是 glob 语义,不识别 ^、$、d 等正则元字符。
- 适合替代
filepath.Glob处理复杂层级,但别指望它解析(test|e2e)_.*.go - 兼容性好,API 几乎和标准库一致,替换成本低
- 如果项目已用
doublestar,又临时需要正则逻辑,建议保持分离:先用它缩小范围,再用regexp精筛
路径正则容易忽略的边界:大小写、分隔符、根路径
实际跑起来经常漏掉几个关键点,导致本地 OK、CI 失败,或 Linux 下正常、Windows 下不匹配。
- 正则默认区分大小写;Go 源码文件名通常小写,但用户可能建
MyTest.go,建议加(?i)标志(如(?i)test.*.go) - 绝对路径开头带
/(Unix)或盘符(C:),而WalkDir给的path是相对起始点的;不要写^/src/.*,应从相对路径角度设计 pattern - 用
filepath.Join拼路径,别手拼"dir/" + name—— Windows 下会变成dir/ile.go,后续正则全乱
真正灵活的文件查找,本质是「遍历 + 判断」的组合。正则只是判断环节的一种工具,选对作用对象(全路径?文件名?相对路径?)、处理好平台差异,比追求“一行正则解决”更重要。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











