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  }