抽象语法树(AST)扫描

huangapple go评论84阅读模式
英文:

abstract syntax tree (AST) scan

问题

我正在尝试从Go AST中提取函数调用:

$ cat main.go
package main
import ("fmt"; "go/ast"; "go/token"; "go/parser"; "io/ioutil")

func CalledFuncs(n ast.Node) bool {
    switch n.(type) {
    case *ast.CallExpr:
        l := ast.CallExpr(n).Lparen
        r := ast.CallExpr(n).Right
        fmt.Printf("call %d( ... %d)\n",l,r)
    }
    return true
}

func main() {
    fset := token.NewFileSet()
    src,_ := ioutil.ReadFile("simple.go")
    f, _ := parser.ParseFile(fset,">>",src,0)
    ast.Inspect(f, CalledFuncs)
}

但是Go编译器报错,说我不能进行类型转换:

$ go build -o main main.go
# command-line-arguments
./main.go:7:26: cannot convert n (type ast.Node) to type ast.CallExpr
./main.go:8:26: cannot convert n (type ast.Node) to type ast.CallExpr

我可能漏掉了什么。

英文:

I'm trying to extract function calls from go AST:

$ cat main.go
package main
import ("fmt"; "go/ast"; "go/token"; "go/parser"; "io/ioutil")

func CalledFuncs(n ast.Node) bool {
    switch n.(type) {
    case *ast.CallExpr:
        l := ast.CallExpr(n).Lparen
        r := ast.CallExpr(n).Right
        fmt.Printf("call %d( ... %d)\n",l,r)
    }
    return true
}

func main() {
	fset := token.NewFileSet()
    src,_ := ioutil.ReadFile("simple.go")
	f, _ := parser.ParseFile(fset,">>",src,0)
	ast.Inspect(f, CalledFuncs)
}

But the go compiler complains I can't do the casting:

$ go build -o main main.go
# command-line-arguments
./main.go:7:26: cannot convert n (type ast.Node) to type ast.CallExpr
./main.go:8:26: cannot convert n (type ast.Node) to type ast.CallExpr

I'm probably missing something here.

答案1

得分: 1

https://golang.org/ref/spec#Type_switches

TypeSwitchGuard可以包含短变量声明。当使用该形式时,变量在每个子句的隐式块的末尾声明。在仅列出一个类型的子句中,变量具有该类型;否则,变量具有TypeSwitchGuard中表达式的类型。

这意味着你可以这样做:

func CalledFuncs(n ast.Node) bool {
	switch x := n.(type) {
	case *ast.CallExpr:
		l := x.Lparen
		r := x.Rparen
		fmt.Printf("call %d( ... %d)\n", l, r)
	}
	return true
}
英文:

https://golang.org/ref/spec#Type_switches

> The TypeSwitchGuard may include a short variable declaration. When
> that form is used, the variable is declared at the end of the
> TypeSwitchCase in the implicit block of each clause. In clauses with a
> case listing exactly one type, the variable has that type; otherwise,
> the variable has the type of the expression in the TypeSwitchGuard.

That means that you can do the following:

func CalledFuncs(n ast.Node) bool {
	switch x := n.(type) {
	case *ast.CallExpr:
		l := x.Lparen
		r := x.Rparen
		fmt.Printf("call %d( ... %d)\n", l, r)
	}
	return true
}

huangapple
  • 本文由 发表于 2021年8月1日 21:58:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/68611125.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定