Search code examples
goreflection

Golang: Is there a way to iterate over a slice in a generic way using reflect?


Is there a way to iterate over a slice in a generic way using reflection?

type LotsOfSlices struct {
    As []A
    Bs []B
    Cs []C
    //.... and lots more of these
}

type A struct {
    F string
    //.... and lots of other stufff that's different from the other structs
}

type B struct {
    F string
    //.... and lots of other stufff that's different from the other structs
}

type C struct {
    F string
    //.... and lots of other stufff that's different from the other structs
}

I want to use reflection to reduce code complexity and duplicate code. Is this possible? Is this a bad idea?

For example, not this:

func processData(l LotsOfSlice){
    for _, a := range l.As{
        // use a.F
    }
    for _, b := range l.Bs{
        // use b.F
    }
    for _, c := range l.Cs{
        // use c.F
    }
    ...
}

But something like this instead:

func processData(l LotsOfSlices){
    t := reflect.TypeOf(l)
    for i := 0; i < t.NumField(); i++ {
        zs := reflect.ValueOf(l).Field(i).Interface()
        for _, z := range zs{
            // use z.F
        }
    }
}

Solution

  • Use Value.Len and Value.Index to iterate over an array or slice:

    func processData(l LotsOfSlices) {
        v := reflect.ValueOf(l)
        for i := 0; i < v.NumField(); i++ {
            f := v.Field(i)
            if f.Kind() != reflect.Slice {
                continue
            }
            for i := 0; i < f.Len(); i++ {
                e := f.Index(i)
                s := e.FieldByName("F")
                // Do something with s
            }
        }
    }