the*_*ses 5 types static-analysis go
如何通过静态分析判断变量的类型?
假设我有以下代码:
func doSomething(x interface{}) {}
func main() {
p := Person()
doSomething(p)
}
Run Code Online (Sandbox Code Playgroud)
而我想分析一下doSomething(person)
,通过静态分析是否可以得到Person的类型?
如果有多个级别的分配怎么办?
p1 := Person()
p2 := p1
doSomething(p2)
Run Code Online (Sandbox Code Playgroud)
或者
parent := Parent()
p := Parent.Child() // type Person
doSomething(p)
Run Code Online (Sandbox Code Playgroud)
用例是我有一个在(非常大的)代码库中常用的通用函数,并且想引入该函数的新类型安全版本。为此,我希望自动确定函数的“类型”并相应地重构它:
// old
DB.InsertRow(person)
// new
Person.InsertRow(person)
Run Code Online (Sandbox Code Playgroud)
使用Golang 静态标识符解析to use的建议golang.org/x/tools/go/types
,我发现这对于该包来说非常简单golang.org/x/tools/go/analysis
,它具有可用的类型信息以及解析的 ast。
这是我的解决方案:
package rewriter
import (
"go/ast"
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"
"golang.org/x/tools/go/ast/inspector"
)
func run(pass *analysis.Pass) (interface{}, error) {
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
nodeFilter := []ast.Node{
(*ast.CallExpr)(nil),
}
inspect.Nodes(nodeFilter, func(node ast.Node, push bool) bool {
callExpr, ok := node.(*ast.CallExpr)
if !ok {
return true
}
funcExpr, ok := callExpr.Fun.(*ast.SelectorExpr)
if !ok {
return true
}
// check method name
if funcExpr.Sel.Name != "doSomething" {
return true
}
for _, arg := range callExpr.Args {
// lookup type of the arg
argType := pass.TypesInfo.Types[arg].Type
if argType.String() == "*rewriter.Person" {
// do whatever you want here
}
}
return false
})
return nil, nil
}
Run Code Online (Sandbox Code Playgroud)
人们可以对此进行扩展以查看方法的接收者并根据需要添加重构逻辑(使用analysis.Diagnostic)。