Golang中如何使用go/packages包的"pattern"参数
Golang中如何使用go/packages包的"pattern"参数
对于熟悉 golang.org/x/tools/go/packages 包的人来说,有没有办法在 Load 函数中指定一个 pattern,以便捕获给定目录路径(例如 Go 项目的根目录)内的所有包?在阅读了该包的文档后,我未能找到以这种方式指定模式的方法。
文档确实解释了通配符字符串 “…”(我将其附加到当前工作目录),但将其附加到项目根目录后,没有包被进行类型检查。
以下代码是我当前的方法。其问题之一是,共享相同包名但不在同一目录下的文件(例如在不同目录中定义的 package main)会被视为独立的包:
c := &packages.Config{
Mode: packages.NeedName | packages.NeedTypesInfo | packages.NeedSyntax,
Dir: rootDir,
}
err := filepath.Walk(rootDir, func(path string, info os.FileInfo, e error) error {
if info.IsDir() {
pkgs, err := packages.Load(c, path)
if err != nil {
log.Panicln(err)
}
if pkgs != nil {
for _, pkg := range pkgs {
log.Println(pkg.Name)
}
}
. . .
产生了以下输出:
2022/04/18 22:17:55
2022/04/18 22:17:55
2022/04/18 22:17:55 main
2022/04/18 22:17:55 main
2022/04/18 22:17:56 mypkg
2022/04/18 22:17:56 resolver
2022/04/18 22:17:56 testpkg
空白的包名代表根目录(即 go-types)和一个与 IDE 相关的目录(即 go-types/.idea)。
以下是我的目录结构,仅供参考:
go-types/
.idea/
[IDE-related files]
cmd/
change/
main.go
main.go
mpkg/
src.go
resolver/
exported.go
util.go
testpkg/
exported.go
任何帮助都将不胜感激!如果有任何不清楚的地方,请告诉我!
更多关于Golang中如何使用go/packages包的"pattern"参数的实战教程也可以访问 https://www.itying.com/category-94-b0.html
你期望你的测试输出什么?
更多关于Golang中如何使用go/packages包的"pattern"参数的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
感谢回复!我想我可能已经找到了问题的解决方案。关于我预期的输出,经过进一步观察,我现在认为给定的输出应该是预期的行为。
我主要关心的是找到一个模式,这样我就不必通过 filepath.Walk(...) 来遍历文件树。在仔细查阅文档后,我发现使用通配符时,我缺少的只是一个末尾的斜杠(例如,使用 /path/to/working/dir/... 而不是 /path/to/working/dir...)。使用这个方法,我得到了以下输出:
2022/04/19 09:20:45 resolver
2022/04/19 09:20:45 main
2022/04/19 09:20:45 main
2022/04/19 09:20:45 testpkg
2022/04/19 09:20:45 mypkg
这基本上与我上面的输出相同,其中似乎不包含没有 Go 文件的目录。
我找到的正确使用该模式的示例来源:Go Modules Reference - The Go Programming Language
在 go/packages 中使用 pattern 参数时,可以通过 ./... 模式来加载项目根目录下的所有包。你的代码需要调整 packages.Load 的调用方式,而不是使用 filepath.Walk。
以下是修正后的代码示例:
c := &packages.Config{
Mode: packages.NeedName | packages.NeedTypesInfo | packages.NeedSyntax,
Dir: rootDir,
}
pkgs, err := packages.Load(c, "./...")
if err != nil {
log.Fatal(err)
}
for _, pkg := range pkgs {
if pkg.Name != "" {
log.Println(pkg.Name, pkg.PkgPath)
}
}
关键点:
Dir字段设置为项目根目录rootDirpackages.Load的 pattern 参数使用"./..."- 这会递归加载
rootDir目录及其所有子目录中的 Go 包
对于你的目录结构,这会正确加载:
cmd/change/main.go(package main)cmd/main.go(package main)mpkg/src.go(package mypkg)resolver/中的文件 (package resolver)testpkg/中的文件 (package testpkg)
注意:packages.Load 会自动处理包名相同但路径不同的情况(如不同目录的 package main),每个都会被识别为独立的包。空包名通常表示目录不是有效的 Go 包(如 .idea/ 目录),可以通过检查 pkg.Name != "" 来过滤掉。

