mercredi 7 mars 2018

Using reflection to iterate over struct's struct members and calling a method on it

I have a struct that has one or more struct members. Each member is expected to implement a Validator interface.

I want to use reflection to iterate over all struct members and call the interface's Validate() method. For example:

package main

import "fmt"
import "reflect"

type Validator interface {
    Validate()
}

type T1 struct {
    S string
}

func (p *T1) Validate() {
    fmt.Println("HERE 1")
}

type T2 struct {
    S string
}

func (p *T2) Validate() {
    fmt.Println("HERE 2")
}

type Top struct {
    S1 T1
    S2 T2
}

func main() {
    var t Top

    r := reflect.ValueOf(t)
    for i := 0; i < r.NumField(); i++ {
        f := r.Field(i)
        if f.Kind() == reflect.Struct {
            validator := f.Interface().(Validator)
            validator.Validate()
        }
    }
}

When run, it outputs:

panic: interface conversion: main.T1 is not main.Validator: missing method Validate

If I change the Validate() methods to accept value (rather than pointer) receivers, then it works. However, I want to use pointer receivers since the structs may grow to be large.

How can I change the reflection code to work where the methods are defined taking pointer receivers?

I also tried using this line:

            validator := f.Addr().Interface().(Validator)

to get a pointer, but it then outputs:

panic: reflect.Value.Addr of unaddressable value





Aucun commentaire:

Enregistrer un commentaire