英文:
How to parse a method declaration?
问题
我正在尝试解析一个方法声明。基本上,我需要获取接收器基本类型(type hello)和返回类型(notype和error)的语法节点。ast包似乎很简单,但出于某种原因,我没有得到我需要的数据(即字段报告为nil)。
唯一有用的数据似乎只提供在Object -> Decl字段中,该字段的类型为interface{},所以我不认为我可以序列化它。
任何帮助将不胜感激。以下是代码:
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)
			}
		}
	}
}
英文:
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)
			}
		}
	}
}
答案1
得分: 9
要获取类型,您需要查看Type属性,它可以是ast.StarExpr或ast.Ident。
请看这个示例:
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)
			}
		}
	}
}
您可以在这里查看示例。
英文:
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)
			}
		}
	}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论