drnrxv9383 2017-10-03 13:19
浏览 60
已采纳

如何使用Go解析方法或函数中的语句

I would like to parse go code, and more especially the content of a function.

So far it's pretty easy to get the function declaration with the parser.ParseFile function.

package main

import (
    "fmt"
    "go/parser"
    "go/token"
    "go/ast"
    "log"
)

var code = []byte(`
package main

import (
    "fmt"
)

func GetFoo() {
    test := foo()
    fmt.Println(test)
}

func foo() int {
    return 0
}
`)

func main() {
    fset := token.NewFileSet()
    f, err := parser.ParseFile(fset, "", code, parser.ParseComments)
    if err != nil {
        log.Fatal(err)
    }

    for _, decl := range f.Decls {
        switch t := decl.(type) {
        // That's a func decl !
        case *ast.FuncDecl:
            fmt.Printf("Function name: %v
", t.Name)
            // Now I would like to access to the test var and get its type
            // Must be int, because foo() returns an int
        }
    }

}

Now I would like to access to the test var and get its type, but I am a little bit lost. I have seen the decl.Body.List to iterate over the statements but I can get that my test var is an int

Thank you for your precious help !

https://play.golang.org/p/Y8uwM-CDWy

  • 写回答

1条回答 默认 最新

  • donglv6960 2017-10-05 08:47
    关注

    Thanks to JimB and his hint about go/types, here's how I could get the signature of my method

    package main
    
    import (
        "fmt"
        "go/ast"
        "go/importer"
        "go/parser"
        "go/token"
        "go/types"
        "log"
    )
    
    var code = []byte(`
    package main
    
    import (
        "fmt"
    )
    
    func GetFoo() {
        test := foo()
        fmt.Println(test)
    }
    
    func foo() int {
        return 0
    }
    `)
    
    func main() {
        fset := token.NewFileSet()
        f, err := parser.ParseFile(fset, "", code, parser.ParseComments)
        if err != nil {
            log.Fatal(err)
        }
    
        conf := types.Config{Importer: importer.Default()}
        pkg, err := conf.Check("cmd", fset, []*ast.File{f}, nil)
        scope := pkg.Scope()
    
        for _, decl := range f.Decls {
            switch t := decl.(type) {
            // That's a func decl !
            case *ast.FuncDecl:
                for _, s := range t.Body.List {
                    switch as := s.(type) {
                    case *ast.AssignStmt:
                        for _, l := range as.Rhs {
                            switch rh := l.(type) {
                            case *ast.CallExpr:
                                if i, ok := rh.Fun.(*ast.Ident); ok {
                                    ft := scope.Lookup(i.Name)
                                    if ft != nil {
                                        if ftype, ok := ft.(*types.Func); ok {
                                            f := ftype.Type()
                                            if sig, ok := f.(*types.Signature); ok {
                                                // get the returned elements
                                                r := sig.Results()
                                                for i := 0; i < r.Len(); i++ {
                                                    v := r.At(i)
                                                    varTpe := v.Type()
                                                    fmt.Println(varTpe)
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮