188

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!

kostix
  • 51,517
  • 14
  • 93
  • 176
omninonsense
  • 6,644
  • 9
  • 45
  • 66
  • 7
    Here is a very interesting article regarding reflection: http://blog.golang.org/laws-of-reflection Following one of the example from the article: http://play.golang.org/p/_bKAQ3dQlu Note however that you can't lookup non-exported fields with the reflect package (i.e. fields that begins with lowercase) – creack Sep 20 '13 at 21:52

8 Answers8

180

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)
}
nemo
  • 55,207
  • 13
  • 135
  • 135
  • 38
    Yea because go doesn't need generics. Cough, cough :-) Is there a way to get the type of the field? – U Avalos Mar 08 '17 at 05:02
  • 1
    via [`reflect.Value.Type()`](https://golang.org/pkg/reflect/#Value.Type), yes. But note that types are not first-class citizens in go, so you can only instantiate new values of that type using `reflect`. – nemo Mar 08 '17 at 06:10
  • 9
    `v.Field(i).Interface()` panics if you try to access non exported private fields. Just be careful :) – Tarion Mar 09 '17 at 11:03
  • what if I want to check if the struct field is also a struct? when looping?@nemo – Angger Mar 30 '18 at 11:15
  • @Angger see for example https://stackoverflow.com/questions/42065226/how-to-determine-if-type-is-a-struct-in-golang – nemo Mar 30 '18 at 20:28
  • 12
    Using `v.Field(i).CanInterface() ` one can avoid the panic in case of unexported fields. – Pedram Esmaeeli Jun 17 '18 at 07:19
  • 2
    How can I get the field name? – Sathesh May 21 '19 at 15:38
  • In my case I needed the field name of the struct. The technique is very similar to the above answer except that reflect.TypeOf() is used instead of ValueOf(). Also the struct would need to have field tags associated to it. There is actually a field.Tag.Lookup("alias") method: https://golang.org/pkg/reflect/#StructTag . I also see a Get() method for the struct tag in the docs: https://golang.org/pkg/reflect/#StructTag –  Apr 27 '20 at 04:48
  • @Tarion Indeed gotta love incomplete answers – Adonis Dec 28 '21 at 15:31
  • @Adonis feel free to improve it. – nemo Dec 28 '21 at 23:46
  • v.Field(i).Interface() seems to return a copy of the actual value. Is it possible to get the actual one? I'm trying dynamically get pointers to all the actual values of a struct fields using reflection. – Krittam Kothari Mar 13 '22 at 12:22
104

If you want to Iterate through the Fields and Values of a struct then you can use the below Go code as a reference.

package main

import (
    "fmt"
    "reflect"
)

type Student struct {
    Fname  string
    Lname  string
    City   string
    Mobile int64
}

func main() {
    s := Student{"Chetan", "Kumar", "Bangalore", 7777777777}
    v := reflect.ValueOf(s)
    typeOfS := v.Type()

    for i := 0; i< v.NumField(); i++ {
        fmt.Printf("Field: %s\tValue: %v\n", typeOfS.Field(i).Name, v.Field(i).Interface())
    }
}

Run in playground

Note: If the Fields in your struct are not exported then the v.Field(i).Interface() will give panic panic: reflect.Value.Interface: cannot return value obtained from unexported field or method.

Community
  • 1
  • 1
Chetan Kumar
  • 1,331
  • 1
  • 10
  • 16
35

Go 1.17 (Q3 2021) should add a new option, through commit 009bfea and CL 281233, fixing issue 42782.

reflect: add VisibleFields function

When writing code that reflects over a struct type, it's a common requirement to know the full set of struct fields, including fields available due to embedding of anonymous members while excluding fields that are erased because they're at the same level as another field with the same name.

The logic to do this is not that complex, but it's a little subtle and easy to get wrong.

This CL adds a new reflect.VisibleFields() function to the reflect package that returns the full set of effective fields that apply in a given struct type.

fields := reflect.VisibleFields(typ)
for j, field := range fields {
    ...
}

Example,

type employeeDetails struct {
    id          int16
    name        string
    designation string
}
func structIterator() {
    fields := reflect.VisibleFields(reflect.TypeOf(struct{ employeeDetails }{}))
    for _, field := range fields {
        fmt.Printf("Key: %s\tType: %s\n", field.Name, field.Type)
    }
}
arif
  • 579
  • 1
  • 7
  • 21
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
7

Maybe too late :))) but there is another solution that you can find the key and value of structs and iterate over that

package main

import (
    "fmt"
    "reflect"
)

type person struct {
    firsName string
    lastName string
    iceCream []string
}

func main() {
    u := struct {
        myMap    map[int]int
        mySlice  []string
        myPerson person
    }{
        myMap:   map[int]int{1: 10, 2: 20},
        mySlice: []string{"red", "green"},
        myPerson: person{
            firsName: "Esmaeil",
            lastName: "Abedi",
            iceCream: []string{"Vanilla", "chocolate"},
        },
    }
    v := reflect.ValueOf(u)
    for i := 0; i < v.NumField(); i++ {
        fmt.Println(v.Type().Field(i).Name)
        fmt.Println("\t", v.Field(i))
    }
}
and there is no *panic* for v.Field(i)
Esmaeil Abedi
  • 79
  • 1
  • 2
  • 3
    Hi and welcome to Stack Overflow! Please take the [tour](https://stackoverflow.com/tour). Thank for contributing an answer (age of the question doesn't matter). Can you explain a bit more how your answer solves the problem? – Jeanne Dark Nov 25 '20 at 18:55
0

use this:

type x struct {
    Id  int
    jsj int
}
func main() {
    x2 := x{jsj: 10, Id: 5}
    v := reflect.ValueOf(x2)
    for i := 0; i < v.NumField(); i++ {
        fmt.Println(v.Field(i))
    }
}

====>10

====>5

mahdi gadget
  • 83
  • 1
  • 6
-1

Taking Chetan Kumar solution and in case you need to apply to a map[string]int

package main

import (
    "fmt"
    "reflect"
)

type BaseStats struct {
    Hp           int
    HpMax        int
    Mp           int
    MpMax        int
    Strength     int
    Speed        int
    Intelligence int
}

type Stats struct {
    Base map[string]int
    Modifiers []string
}

func StatsCreate(stats BaseStats) Stats {
    s := Stats{
        Base: make(map[string]int),
    }

    //Iterate through the fields of a struct
    v := reflect.ValueOf(stats)
    typeOfS := v.Type()

    for i := 0; i< v.NumField(); i++ {
        val := v.Field(i).Interface().(int)
        s.Base[typeOfS.Field(i).Name] = val
    }
    return s
}

func (s Stats) GetBaseStat(id string) int {
    return s.Base[id]
}


func main() {
    m := StatsCreate(BaseStats{300, 300, 300, 300, 10, 10, 10})

    fmt.Println(m.GetBaseStat("Hp"))
}


Chetan Kumar
  • 1,331
  • 1
  • 10
  • 16
STEEL
  • 8,955
  • 9
  • 67
  • 89
-1

Use reflect package. First, get the type of variable with reflect.TypeOf and get numbers of elements with reflect.NumField.To obtain the values of the fields iteratively of a structure must reflect the variable and use the function rg.Elem().Field(i)

package main

import (
    "fmt"
    "reflect"
)

type Gopher struct {
    Name  string
    Color string
    Year  int
}

func main() {
    g := Gopher{Name: "AAA", Color: "BBBB", Year: 2021}

    gtype := reflect.TypeOf(g)

    numFields := gtype.NumField()

    rg := reflect.ValueOf(&g)

    for i := 0; i < numFields; i++ {
        fmt.Println(rg.Elem().Field(i))
    }
}
Lin Du
  • 88,126
  • 95
  • 281
  • 483
-2

In Go, you can use the reflect package to iterate through the fields of a struct. The reflect package allows you to inspect the properties of values at runtime, including their type and value. Here's an example of how to iterate through the fields of a struct:

Go Playground

package main

import (
    "fmt"
    "reflect"
)

type Movie struct {
    Name string
    Year int
}

func main() {
    p := Movie{"The Dark Knight", 2008}

    val := reflect.ValueOf(p)
    typ := val.Type()

    for i := 0; i < val.NumField(); i++ {
        field := val.Field(i)
        fieldType := typ.Field(i)

        fmt.Printf("Field Name: %s, Field Value: %v\n", fieldType.Name, field.Interface())
    }
}

Output:

Field Name: Name, Field Value: The Dark Knight
Field Name: Age, Field Value: 2008
Ilya
  • 1
  • 1