猿问

解析 go src,尝试将 *ast.GenDecl 转换为 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


慕村225694
浏览 144回答 1
1回答

Smart猫小萌

使用 AST 时,我发现使用spew包转储示例很有帮助:&nbsp; &nbsp; fset := token.NewFileSet()&nbsp; &nbsp; f, _ := parser.ParseFile(fset, "/tmp/tmp.go", `package service ....`)&nbsp; &nbsp; spew.Dump(f)我发现从 spew 输出中编写所需的代码很容易。这里有一些代码可以帮助您入门。它打印接口和方法名称:package mainimport (&nbsp; "fmt"&nbsp; "go/ast"&nbsp; "go/parser"&nbsp; "go/token")func main() {&nbsp; fset := token.NewFileSet()&nbsp; f, _ := parser.ParseFile(fset, "/tmp/tmp.go", `package service&nbsp; &nbsp; type ServiceInterface interface {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Create(NewServiceRequest) (JsonResponse, error)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Delete(DelServiceRequest) (JsonResponse, error)&nbsp; &nbsp; }`, 0)&nbsp; for _, x := range f.Decls {&nbsp; &nbsp; if x, ok := x.(*ast.GenDecl); ok {&nbsp; &nbsp; &nbsp; &nbsp; if x.Tok != token.TYPE {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; for _, x := range x.Specs {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if x, ok := x.(*ast.TypeSpec); ok {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; iname := x.Name&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if x, ok := x.Type.(*ast.InterfaceType); ok {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for _, x := range x.Methods.List {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if len(x.Names) == 0 {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mname := x.Names[0].Name&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("interface:", iname, "method:", mname)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; }}http://play.golang.org/p/eNyB7O6FIc
随时随地看视频慕课网APP

相关分类

Go
我要回答