Iterate through the fields of a struct in Go

前端 未结 4 1480
野的像风
野的像风 2020-11-28 20:55

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_numbe         


        
相关标签:
4条回答
  • 2020-11-28 21:01

    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"))
    }
    
    
    
    0 讨论(0)
  • 2020-11-28 21:06

    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.

    0 讨论(0)
  • 2020-11-28 21:20

    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)
    }
    
    0 讨论(0)
  • 2020-11-28 21:21

    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)
    
    0 讨论(0)
提交回复
热议问题