209

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!

1
  • 7
    Here is a very interesting article regarding reflection: blog.golang.org/laws-of-reflection Following one of the example from the article: 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) Commented Sep 20, 2013 at 21:52

8 Answers 8

193

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) } 
Sign up to request clarification or add additional context in comments.

11 Comments

Yea because go doesn't need generics. Cough, cough :-) Is there a way to get the type of the field?
via 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.
v.Field(i).Interface() panics if you try to access non exported private fields. Just be careful :)
Using v.Field(i).CanInterface() one can avoid the panic in case of unexported fields.
How can I get the field name?
|
115

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.

Comments

51

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(employeeDetails{})) for _, field := range fields { fmt.Printf("Key: %s\tType: %s\n", field.Name, field.Type) } } 

1 Comment

struct{ employeeDetails }{} can be replace with employeeDetails{}
8

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) 

1 Comment

Hi and welcome to Stack Overflow! Please take the 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?
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

Comments

-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")) } 

Comments

-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)) } } 

Comments

-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 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.