为了账号安全,请及时绑定邮箱和手机立即绑定

解析 go src,尝试将 *ast.GenDecl 转换为 types.Interface

解析 go src,尝试将 *ast.GenDecl 转换为 types.Interface

Go
慕村225694 2021-11-22 18:27:19
我正在尝试解析包含接口的 go 源文件并找到接口定义的方法/签名。我正在使用 ast 来解析文件。我能够获得一些高级声明,例如 *ast.GenDecl,但我无法进入下一个级别来确定此类型是否为接口及其方法。这是一个脚手架类型的问题,我试图解决用户定义服务接口和工具将构建服务框架的问题package mainimport (        "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
查看完整描述

1 回答

?
Smart猫小萌

TA贡献1911条经验 获得超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


查看完整回答
反对 回复 2021-11-22
  • 1 回答
  • 0 关注
  • 143 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信