Search code examples
gogo-reflect

Iterate through the fields of a struct in Go


Basically, the only way (that I know of) to iterate through the values of the fields of a struct is like this:

type Example struct {
    a_number uint32
    a_string string
}

//...

r := &Example{(2 << 31) - 1, "...."}:
for _, d:= range []interface{}{ r.a_number, r.a_string, } {
  //do something with the d
}

I was wondering, if there's a better and more versatile way of achieving []interface{}{ r.a_number, r.a_string, }, so I don't need to list each parameter individually, or alternatively, is there a better way to loop through a struct?

I tried to look through the reflect package, but I hit a wall, because I'm not sure what to do once I retrieve reflect.ValueOf(*r).Field(0).

Thanks!


Solution

  • After you've retrieved the reflect.Value of the field by using Field(i) you can get a interface value from it by calling Interface(). Said interface value then represents the value of the field.

    There is no function to convert the value of the field to a concrete type as there are, as you may know, no generics in go. Thus, there is no function with the signature GetValue() T with T being the type of that field (which changes of course, depending on the field).

    The closest you can achieve in go is GetValue() interface{} and this is exactly what reflect.Value.Interface() offers.

    The following code illustrates how to get the values of each exported field in a struct using reflection (play):

    import (
        "fmt"
        "reflect"
    )
    
    func main() {
        x := struct{Foo string; Bar int }{"foo", 2}
    
        v := reflect.ValueOf(x)
    
        values := make([]interface{}, v.NumField())
    
        for i := 0; i < v.NumField(); i++ {
            values[i] = v.Field(i).Interface()
        }
    
        fmt.Println(values)
    }