如何解析方法声明? [英] How to parse a method declaration?
问题描述
我试图解析一个方法声明。基本上我需要得到接收器基类型的语法节点(类型hello
)和返回类型( notype
和错误
)。 ast
包似乎很简单,但由于某种原因,我没有得到我需要的数据(即字段被报告为零)。
唯一有用的数据似乎只在 Object中提供 - > Decl
字段的类型是 interface {}
,所以我不认为我可以序列化它。
任何帮助将不胜感激。代码如下:
包主
导入(
fmt
go / ast
go / parser
go / token
)
func main(){
// src是我们想要检查AST的输入。
src:=`
包mypack
//类型hello是一个很酷的类型
类型hello字符串
//类型notype不是那么酷
类型notype int
// func printme就像没有别的。
func(x * hello)printme(s string)(notype,error){
return 0,nil
}
`
//通过解析来创建AST SRC。
fset:= token.NewFileSet()//位置相对于fset
f,err:= parser.ParseFile(fset,src.go,src,0)
if err! =无{
恐慌(错误)
}
//检查AST并找到我们的函数
var mf ast.FuncDecl
ast.Inspect f,func(n ast.Node)bool {
switch x:= n。(type){
case * ast.FuncDecl:
mf = * x
}
返回true
})
如果mf.Recv!= nil {
fmt.Printf(\\\
receivers:)
for _,v :=范围mf.Recv.List {
fmt.Printf(,tag%v,v.Tag)
for _,xv:=范围v.Names {
fmt.Printf (name%v,decl%v,data%v,type%v,
xv.Name,xv.Obj.Decl,xv.Obj.Data,xv.Obj.Type)
}
}
}
}
$ b $为了得到这个类型,你需要看看 Type
属性,它可能是一个 ast.StarExpr
或 ast.Ident
。 看这个:
<$ p
$ b $ go $ / $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ go / token
)
func main(){
// src是我们要检查AST的输入。
src:=`
包mypack
//类型hello是一个很酷的类型
类型hello字符串
//类型notype不是那么酷
类型notype int
// printme与其他类似。
func(x * hello)printme(s string)(notype,error){
return 0,nil
}
`
//通过解析来创建AST SRC。
fset:= token.NewFileSet()//位置相对于fset
f,err:= parser.ParseFile(fset,src.go,src,0)
if err! =无{
恐慌(错误)
}
//检查AST并找到我们的函数
var mf ast.FuncDecl
ast.Inspect f,func(n ast.Node)bool {
switch x:= n。(type){
case * ast.FuncDecl:
mf = * x
}
返回true
})
if mf.Recv!= nil {
for _,v:= range mf.Recv.List {
fmt.Print (recv type:)
switch xv:= v.Type。(type){
case * ast.StarExpr:
if si,ok:= xv.X。(* ast .Ident); OK {
fmt.Println(si.Name)
}
case * ast.Ident:
fmt.Println(xv.Name)
}
}
}
}
I'm trying to parse a method declaration. Basically I need to get the syntax node of the receiver base type (type hello
) and the return types (notype
and error
). The ast
package seems straightforward but for some reason I don't get the data I need (i.e. the fields are reported nil).
The only useful data seems provided only in Object -> Decl
field which is of type interface{}
so I don't think I can serialize it.
Any help would be appreciated. Code below:
package main
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
)
func main() {
// src is the input for which we want to inspect the AST.
src := `
package mypack
// type hello is a cool type
type hello string
// type notype is not that cool
type notype int
// func printme is like nothing else.
func (x *hello)printme(s string)(notype, error){
return 0, nil
}
`
// Create the AST by parsing src.
fset := token.NewFileSet() // positions are relative to fset
f, err := parser.ParseFile(fset, "src.go", src, 0)
if err != nil {
panic(err)
}
// Inspect the AST and find our function
var mf ast.FuncDecl
ast.Inspect(f, func(n ast.Node) bool {
switch x := n.(type) {
case *ast.FuncDecl:
mf = *x
}
return true
})
if mf.Recv != nil {
fmt.Printf("\n receivers:")
for _, v := range mf.Recv.List {
fmt.Printf(",tag %v", v.Tag)
for _, xv := range v.Names {
fmt.Printf("name %v, decl %v, data %v, type %v",
xv.Name, xv.Obj.Decl, xv.Obj.Data, xv.Obj.Type)
}
}
}
}
To get the type you need to look at the Type
attribute which could be an ast.StarExpr
or an ast.Ident
.
Here take a look at this :
package main
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
)
func main() {
// src is the input for which we want to inspect the AST.
src := `
package mypack
// type hello is a cool type
type hello string
// type notype is not that cool
type notype int
// printme is like nothing else.
func (x *hello)printme(s string)(notype, error){
return 0, nil
}
`
// Create the AST by parsing src.
fset := token.NewFileSet() // positions are relative to fset
f, err := parser.ParseFile(fset, "src.go", src, 0)
if err != nil {
panic(err)
}
// Inspect the AST and find our function
var mf ast.FuncDecl
ast.Inspect(f, func(n ast.Node) bool {
switch x := n.(type) {
case *ast.FuncDecl:
mf = *x
}
return true
})
if mf.Recv != nil {
for _, v := range mf.Recv.List {
fmt.Print("recv type : ")
switch xv := v.Type.(type) {
case *ast.StarExpr:
if si, ok := xv.X.(*ast.Ident); ok {
fmt.Println(si.Name)
}
case *ast.Ident:
fmt.Println(xv.Name)
}
}
}
}
这篇关于如何解析方法声明?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!