Get a simple string representation of the type of structure fields

Using the Gos ast package , I iterate over the list of structs fields as follows:

type Thing struct { Field1 string Field2 []int Field3 map[byte]float64 } // typ is a *ast.StructType representing the above for _, fld := range typ.Fields.List { // get fld.Type as string } 

... and would like to get a simple string representation of fld.Type, as shown in the source code, for example: "[] int" or "map [byte] float64".

The ast package field type The Type property is Expr, so Ive discovered that I go out into the weeds using type switches and processing each type - when my only goal is to get out of a simple line to the right of each field name, which seems to be to be easier.

Is there an easy way?

+7
go abstract-syntax-tree
source share
2 answers

There are two things you can get here: one is the type of expression that will ultimately be resolved at compile time, and the other is the code that defines this type.

Delving into the documents, I do not believe that the first is available. However, you can get a later version using End() and Pos() on Node .

Quick example program:

 package main import ( "fmt" "go/ast" "go/parser" "go/token" ) func main() { src := ` package foo type Thing struct { Field1 string Field2 []int Field3 map[byte]float64 }` fset := token.NewFileSet() f, err := parser.ParseFile(fset, "", src, 0) if err != nil { panic(err) } // hard coding looking these up typeDecl := f.Decls[0].(*ast.GenDecl) structDecl := typeDecl.Specs[0].(*ast.TypeSpec).Type.(*ast.StructType) fields := structDecl.Fields.List for _, field := range fields { typeExpr := field.Type start := typeExpr.Pos() - 1 end := typeExpr.End() - 1 // grab it in source typeInSource := src[start:end] fmt.Println(typeInSource) } } 

Fingerprints:

 string []int map[byte]float64 

I'm through this together on the golang playground if you want to mess with her.

+11
source share

I found a way to do this without using the source code as a reference for simple members (not slices, arrays, or structures):

  for _, field := range fields { switch field.Type.(type) { case *ast.Ident: stype := field.Type.(*ast.Ident).Name // The type as a string tag = "" if field.Tag != nil { tag = field.Tag.Value //the tag as a string } name := field.Names[0].Name //name as a string ... 

For complex members, you just need another case statement (IE: case *ast.ArrayType: .

0
source share

All Articles