go ast解析出函数参数名
做了一个gin的扩展,想把请求参数里的内容自动传到方法参数里,需要用到反射,但是反射有个缺点是无法拿到参数名(注意:不是函数名)
做的以下测试。
测试代码如下
package main
import (
"go/ast"
"go/parser"
"go/token"
"log"
)
func main() {
src := []byte(`
package test
import "fmt"
func sayHello(msg string) {
fmt.Println("helloworld" + msg)
}`)
fset := token.NewFileSet()
file, err := parser.ParseFile(fset, "", src, 0)
if err != nil {
log.Fatal(err)
}
ast.Print(fset, file)
}
以下是ast解析内容,注意第42行函数sayHello
的参数名msg
已经可以拿到了
0 *ast.File {
1 . Package: 2:1
2 . Name: *ast.Ident {
3 . . NamePos: 2:9
4 . . Name: "test"
5 . }
6 . Decls: []ast.Decl (len = 2) {
7 . . 0: *ast.GenDecl {
8 . . . TokPos: 3:1
9 . . . Tok: import
10 . . . Lparen: -
11 . . . Specs: []ast.Spec (len = 1) {
12 . . . . 0: *ast.ImportSpec {
13 . . . . . Path: *ast.BasicLit {
14 . . . . . . ValuePos: 3:8
15 . . . . . . Kind: STRING
16 . . . . . . Value: "\"fmt\""
17 . . . . . }
18 . . . . . EndPos: -
19 . . . . }
20 . . . }
21 . . . Rparen: -
22 . . }
23 . . 1: *ast.FuncDecl {
24 . . . Name: *ast.Ident {
25 . . . . NamePos: 4:6
26 . . . . Name: "sayHello"
27 . . . . Obj: *ast.Object {
28 . . . . . Kind: func
29 . . . . . Name: "sayHello"
30 . . . . . Decl: *(obj @ 23)
31 . . . . }
32 . . . }
33 . . . Type: *ast.FuncType {
34 . . . . Func: 4:1
35 . . . . Params: *ast.FieldList {
36 . . . . . Opening: 4:14
37 . . . . . List: []*ast.Field (len = 1) {
38 . . . . . . 0: *ast.Field {
39 . . . . . . . Names: []*ast.Ident (len = 1) {
40 . . . . . . . . 0: *ast.Ident {
41 . . . . . . . . . NamePos: 4:15
42 . . . . . . . . . Name: "msg"
43 . . . . . . . . . Obj: *ast.Object {
44 . . . . . . . . . . Kind: var
45 . . . . . . . . . . Name: "msg"
46 . . . . . . . . . . Decl: *(obj @ 38)
47 . . . . . . . . . }
48 . . . . . . . . }
49 . . . . . . . }
50 . . . . . . . Type: *ast.Ident {
51 . . . . . . . . NamePos: 4:19
52 . . . . . . . . Name: "string"
53 . . . . . . . }
54 . . . . . . }
55 . . . . . }
56 . . . . . Closing: 4:25
57 . . . . }
58 . . . }
59 . . . Body: *ast.BlockStmt {
60 . . . . Lbrace: 4:27
61 . . . . List: []ast.Stmt (len = 1) {
62 . . . . . 0: *ast.ExprStmt {
63 . . . . . . X: *ast.CallExpr {
64 . . . . . . . Fun: *ast.SelectorExpr {
65 . . . . . . . . X: *ast.Ident {
66 . . . . . . . . . NamePos: 5:2
67 . . . . . . . . . Name: "fmt"
68 . . . . . . . . }
69 . . . . . . . . Sel: *ast.Ident {
70 . . . . . . . . . NamePos: 5:6
71 . . . . . . . . . Name: "Println"
72 . . . . . . . . }
73 . . . . . . . }
74 . . . . . . . Lparen: 5:13
75 . . . . . . . Args: []ast.Expr (len = 1) {
76 . . . . . . . . 0: *ast.BinaryExpr {
77 . . . . . . . . . X: *ast.BasicLit {
78 . . . . . . . . . . ValuePos: 5:14
79 . . . . . . . . . . Kind: STRING
80 . . . . . . . . . . Value: "\"helloworld\""
81 . . . . . . . . . }
82 . . . . . . . . . OpPos: 5:27
83 . . . . . . . . . Op: +
84 . . . . . . . . . Y: *ast.Ident {
85 . . . . . . . . . . NamePos: 5:29
86 . . . . . . . . . . Name: "msg"
87 . . . . . . . . . . Obj: *(obj @ 43)
88 . . . . . . . . . }
89 . . . . . . . . }
90 . . . . . . . }
91 . . . . . . . Ellipsis: -
92 . . . . . . . Rparen: 5:32
93 . . . . . . }
94 . . . . . }
95 . . . . }
96 . . . . Rbrace: 6:1
97 . . . }
98 . . }
99 . }
100 . Scope: *ast.Scope {
101 . . Objects: map[string]*ast.Object (len = 1) {
102 . . . "sayHello": *(obj @ 27)
103 . . }
104 . }
105 . Imports: []*ast.ImportSpec (len = 1) {
106 . . 0: *(obj @ 12)
107 . }
108 . Unresolved: []*ast.Ident (len = 2) {
109 . . 0: *(obj @ 50)
110 . . 1: *(obj @ 65)
111 . }
112 }