Тип параметра Go lang func - PullRequest
0 голосов
/ 25 мая 2018

Я пытаюсь найти тип параметра func и его имя для генерации некоторого кода.Я использую ast пакет для него.Я нашел имя параметра, но не могу найти имя типа параметра.

for _, fun := range findFunc(node) { //ast.FuncDecl

    if  fun.Recv != nil {
        for _, field := range fun.Type.Params.List {
            for _, name := range field.Names {
                println(name.Name)  //Func field name
                //How to find field type name here?
            }

        }
    }

}

1 Ответ

0 голосов
/ 25 мая 2018

Вы на правильном пути, FuncType.Params - список (входящих) параметров функции.В его поле List содержатся все параметры типа ast.Field:

type Field struct {
        Doc     *CommentGroup // associated documentation; or nil
        Names   []*Ident      // field/method/parameter names; or nil if anonymous field
        Type    Expr          // field/method/parameter type
        Tag     *BasicLit     // field tag; or nil
        Comment *CommentGroup // line comments; or nil
}

Field.Type содержит тип параметра, который является типом интерфейса ast.Expr просто встраивает ast.Node, который предоставляет вам только начальную и конечную позиции типа в источнике.В принципе этого должно быть достаточно, чтобы получить текстовое представление типа.

Давайте рассмотрим простой пример.Мы проанализируем эту функцию:

func myfunc(i int, s string, err error, pt image.Point, x []float64) {}

И код для печати его параметров, включая имена типов:

src := `package xx
func myfunc(i int, s string, err error, pt image.Point, x []float64) {}`

fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "src.go", src, 0)
if err != nil {
    panic(err)
}
offset := f.Pos()

ast.Inspect(f, func(n ast.Node) bool {
    if fd, ok := n.(*ast.FuncDecl); ok {
        fmt.Printf("Function: %s, parameters:\n", fd.Name)
        for _, param := range fd.Type.Params.List {
            fmt.Printf("  Name: %s\n", param.Names[0])
            fmt.Printf("    ast type          : %T\n", param.Type)
            fmt.Printf("    type desc         : %+v\n", param.Type)
            fmt.Printf("    type name from src: %s\n",
                src[param.Type.Pos()-offset:param.Type.End()-offset])
        }
    }
    return true
})

Вывод (попробуйте на Go Playground ):

Function: myfunc, parameters:
  Name: i
    ast type          : *ast.Ident
    type desc         : int
    type name from src: int
  Name: s
    ast type          : *ast.Ident
    type desc         : string
    type name from src: string
  Name: err
    ast type          : *ast.Ident
    type desc         : error
    type name from src: error
  Name: pt
    ast type          : *ast.SelectorExpr
    type desc         : &{X:image Sel:Point}
    type name from src: image.Point
  Name: x
    ast type          : *ast.ArrayType
    type desc         : &{Lbrack:71 Len:<nil> Elt:float64}
    type name from src: []float64
...