英文:
List all imported types given an import path
问题
我正在尝试在运行时列出给定导入路径中的所有导入类型。示例代码:
package main
import (
"fmt"
"go/importer"
)
func main() {
pkg, err := importer.Default().Import("github.com/aler9/goroslib/pkg/msgs/std_msgs")
if err != nil {
fmt.Println("error:", err)
return
}
for _, declName := range pkg.Scope().Names() {
fmt.Println(declName)
}
}
这会导致错误:
错误:找不到导入:"github.com/aler9/goroslib/pkg/msgs/std_msgs"
是否可以用Golang实现我想要的功能?
注意:
我知道这篇文章:https://stackoverflow.com/questions/56259230/how-to-use-go-importer
通过使用pkg, err := importer.Default().Import("github.com/aler9/goroslib")
,二进制文件会返回一些类型,但它们不是我想要的。
英文:
I am trying to list all imported types from a given import path at runtime. Sample code:
package main
import (
"fmt"
"go/importer"
)
func main() {
pkg, err := importer.Default().Import("github.com/aler9/goroslib/pkg/msgs/std_msgs")
if err != nil {
fmt.Println("error:", err)
return
}
for _, declName := range pkg.Scope().Names() {
fmt.Println(declName)
}
}
This results in error:
> error: can't find import: "github.com/aler9/goroslib/pkg/msgs/std_msgs"
It is possbile to achieve what I want with Golang?
Note:
I am aware of the post: https://stackoverflow.com/questions/56259230/how-to-use-go-importer
By using pkg, err := importer.Default().Import("github.com/aler9/goroslib")
the binary returns a few types but they are not what I want.
答案1
得分: 4
我不知道如何使用go/importer
来做这个,甚至不确定是否可能。
不过,你可以使用golang.org/x/tools/go/packages
包来加载一个包的AST,然后遍历该树来打印出你找到的任何类型声明。
package main
import (
"fmt"
"go/ast"
"go/token"
"golang.org/x/tools/go/packages"
)
func main() {
loadConfig := new(packages.Config)
loadConfig.Mode = packages.NeedSyntax
loadConfig.Fset = token.NewFileSet()
pkgs, err := packages.Load(loadConfig, "encoding/json")
if err != nil {
panic(err)
}
for _, pkg := range pkgs {
for _, syn := range pkg.Syntax {
for _, dec := range syn.Decls {
if gen, ok := dec.(*ast.GenDecl); ok && gen.Tok == token.TYPE {
for _, spec := range gen.Specs {
if ts, ok := spec.(*ast.TypeSpec); ok {
fmt.Println(ts.Name)
}
}
}
}
}
}
}
注意1:上面的示例将打印出导出的类型和未导出的类型。如果你只想打印出导出的类型,你可以添加一个条件来检查ts.Name.IsExported
。
注意2:如果我没记错的话,你想要加载的包 必须 已经在你的模块缓存中,因为packages.Load
不会通过网络下载它,如果它不在缓存中的话。
英文:
I don't know how to do it with go/importer
, or even if it's possible.
However, you could, for example, use the golang.org/x/tools/go/packages
package to load a package's AST and then traverse that tree to print out any type declarations you find.
package main
import (
"fmt"
"go/ast"
"go/token"
"golang.org/x/tools/go/packages"
)
func main() {
loadConfig := new(packages.Config)
loadConfig.Mode = packages.NeedSyntax
loadConfig.Fset = token.NewFileSet()
pkgs, err := packages.Load(loadConfig, "encoding/json")
if err != nil {
panic(err)
}
for _, pkg := range pkgs {
for _, syn := range pkg.Syntax {
for _, dec := range syn.Decls {
if gen, ok := dec.(*ast.GenDecl); ok && gen.Tok == token.TYPE {
for _, spec := range gen.Specs {
if ts, ok := spec.(*ast.TypeSpec); ok {
fmt.Println(ts.Name)
}
}
}
}
}
}
}
NOTE #1: The above example will print exported and unexported types. If you want to print exported only you can add an if condition to check for ts.Name.IsExported
.
NOTE #2: The package you want to load, if I'm not mistaken, must already be in your module cache because packages.Load
will not go over the network and download it if it's not there.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论