英文:
Parsing go src, trying to convert *ast.GenDecl to types.Interface
问题
我正在尝试解析包含接口的Go源文件,并找到接口定义的方法/签名。我正在使用ast来解析文件。我能够获取一些高级声明,比如*ast.GenDecl,但是我无法进一步确定这个类型是否是接口以及它的方法是什么。
这是我正在解决的一个脚手架类型的问题,用户定义了一个服务的接口,然后工具将构建出服务的框架。
package main
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"reflect"
)
func main() {
fset := token.NewFileSet()
f, _ := parser.ParseFile(fset, "/tmp/tmp.go", `package service
type ServiceInterface interface {
Create(NewServiceRequest) (JsonResponse, error)
Delete(DelServiceRequest) (JsonResponse, error)
}`, 0)
for _, v := range f.Decls {
switch t := v.(type) {
case *ast.FuncDecl:
fmt.Println("func ", t.Name.Name)
case *ast.GenDecl:
switch x := t.Specs[0].(type) {
default:
fmt.Println(x, reflect.TypeOf(x))
}
default:
fmt.Printf("skipping %t\n", t)
}
}
}
但是我似乎无法找到关于接口声明内部的任何信息。
&{<nil> ServiceInterface 0x8202d8260 <nil>} *ast.TypeSpec
英文:
I am trying to parse go source files that contain interfaces and find the interfaces defined methods / signatures. I am using ast to parse the file. I am able to get some high level declarations, such as *ast.GenDecl, but I am not able to get to the next level of determining if this type is an interface and what its methods are.
This is for a scaffolding type problem I am trying to solve where a user defines the interface for a service and a tool will build out the skeleton of the service
package main
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"reflect"
)
func main() {
fset := token.NewFileSet()
f, _ := parser.ParseFile(fset, "/tmp/tmp.go", `package service
type ServiceInterface interface {
Create(NewServiceRequest) (JsonResponse, error)
Delete(DelServiceRequest) (JsonResponse, error)
}`, 0)
for _, v := range f.Decls {
switch t := v.(type) {
case *ast.FuncDecl:
fmt.Println("func ", t.Name.Name)
case *ast.GenDecl:
switch x := t.Specs[0].(type) {
default:
fmt.Println(x, reflect.TypeOf(x))
}
default:
fmt.Printf("skipping %t\n", t)
}
}
}
Results in but I cant seem to find anything about the internals of interface declaration at all.
&{<nil> ServiceInterface 0x8202d8260 <nil>} *ast.TypeSpec
答案1
得分: 7
使用AST进行工作时,我发现使用spew包来转储示例非常有帮助:
fset := token.NewFileSet()
f, _ := parser.ParseFile(fset, "/tmp/tmp.go", `package service ....`)
spew.Dump(f)
我发现从spew输出中编写所需的代码很容易。
以下是一些代码,可以帮助你入门。它打印接口和方法名称:
package main
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
)
func main() {
fset := token.NewFileSet()
f, _ := parser.ParseFile(fset, "/tmp/tmp.go", `package service
type ServiceInterface interface {
Create(NewServiceRequest) (JsonResponse, error)
Delete(DelServiceRequest) (JsonResponse, error)
}`, 0)
for _, x := range f.Decls {
if x, ok := x.(*ast.GenDecl); ok {
if x.Tok != token.TYPE {
continue
}
for _, x := range x.Specs {
if x, ok := x.(*ast.TypeSpec); ok {
iname := x.Name
if x, ok := x.Type.(*ast.InterfaceType); ok {
for _, x := range x.Methods.List {
if len(x.Names) == 0 {
continue
}
mname := x.Names[0].Name
fmt.Println("interface:", iname, "method:", mname)
}
}
}
}
}
}
}
你可以在这里查看运行结果:http://play.golang.org/p/eNyB7O6FIc
英文:
When working with the AST, I find it helpful to dump an example using the spew package:
fset := token.NewFileSet()
f, _ := parser.ParseFile(fset, "/tmp/tmp.go", `package service ....`)
spew.Dump(f)
I find it easy to write the required code from the spew output.
Here's some code to get you started. It prints interface and method names:
package main
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
)
func main() {
fset := token.NewFileSet()
f, _ := parser.ParseFile(fset, "/tmp/tmp.go", `package service
type ServiceInterface interface {
Create(NewServiceRequest) (JsonResponse, error)
Delete(DelServiceRequest) (JsonResponse, error)
}`, 0)
for _, x := range f.Decls {
if x, ok := x.(*ast.GenDecl); ok {
if x.Tok != token.TYPE {
continue
}
for _, x := range x.Specs {
if x, ok := x.(*ast.TypeSpec); ok {
iname := x.Name
if x, ok := x.Type.(*ast.InterfaceType); ok {
for _, x := range x.Methods.List {
if len(x.Names) == 0 {
continue
}
mname := x.Names[0].Name
fmt.Println("interface:", iname, "method:", mname)
}
}
}
}
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论