Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get a simple string representation of a struct field’s type

Using Go’s ast package, I am looping over a struct’s field list like so:

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 it appears in the source code, e.g. []int or map[byte]float64.

The ast package field type Type property is an Expr, so I’ve found myself getting off into the weeds using type switches and handling every type specifically – when my only goal is to get out the plain string to the right of each field name, which seems like it should be simpler.

Is there a simple way?

like image 538
Matt Sherman Avatar asked Nov 27 '13 05:11

Matt Sherman


People also ask

How do you change a struct to a string?

(Update: to put the output into a string instead of printing it, use str := fmt. Sprintf("%#v", var) . If size matters you can use %v , but I like %#v because it will also include the field names and the name of the struct type. A third variation is %+v which will include the field names, but not the struct type.

How to give values in struct in golang?

Struct Equalityp1 := Point{3.4, 5.2} p2 := Point{3.4, 5.2} if p1 == p2 { fmt. Println("Point p1 and p2 are equal.") } else { fmt. Println("Point p1 and p2 are not equal.") } }

How to define a struct in golang?

A structure or struct in Golang is a user-defined type that allows to group/combine items of possibly different types into a single type. Any real-world entity which has some set of properties/fields can be represented as a struct. This concept is generally compared with the classes in object-oriented programming.

What is an idiomatic way to customize the representation of a custom struct in a formatted string?

What is an idiomatic way to customize the representation of a custom struct in a formatted string? There is no customizing the string representation of a type. Build it in pieces each time by calling individual fields. Create a wrapper function that accepts your type and outputs a string.


1 Answers

There are two things you could be getting at here, one is the type of an expression as would ultimately be resolved during compilation and the other is the code which would determine that type.

Digging through the docs, I don't believe the first is at all available. You can get at the later, however, by 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)
    }

}

This prints:

string
[]int
map[byte]float64

I through this together in the golang playground, if you want to mess with it.

like image 191
Kevin Montrose Avatar answered Oct 14 '22 18:10

Kevin Montrose