samedi 14 janvier 2017

Golang reflection: cast a type to interface

could you help me understand if this is doable in Go?

I have those 2 structs and i really need to do the validation (later) this way:

type Parent struct {
    Sth              string `fatvalid:"required"`
    SthElse          string `fatvalid:"required"`
    Children         []*Child
    Sth_Fatvalid     string
    SthElse_Fatvalid string
}

type Child struct {
    ChildName          string `fatvalid:"required"`
    ChildAge           uint   `fatvalid:"required"`
    ChildName_Fatvalid string
    ChildAge_Fatvalid  string
}

Then i have this function that should recursively go through each field of the "Parent" struct and all the Child structs and do some validation by setting the appropriate message on the "_Fatvalid" fields:

(i took the original code from http://ift.tt/2iTSepw and tried to make it work for me)

func Fatvalid(iface interface{}) error {

    ifv := reflect.ValueOf(iface)

    if ifv.Kind() != reflect.Ptr {
        return errors.New("Not a pointer")
    }

    ift := reflect.Indirect(ifv).Type()

    for i := 0; i < ift.NumField(); i++ {

        v := ift.Field(i)
        if strings.HasSuffix(v.Name, "_Fatvalid") {
            continue
        }

        el := reflect.Indirect(ifv.Elem().FieldByName(v.Name))
        el_validation := reflect.Indirect(ifv.Elem().FieldByName(v.Name + "_Fatvalid"))

        switch el.Kind() {

        case reflect.String:
            if el_validation.CanSet() {
                fmt.Println("obrabiam: ", v.Name)
                el_validation.SetString("This validation returns error!")
            }
        case reflect.Slice:

            if slice, ok := el.Interface().([]*Child); ok {
                for _, input := range slice {
                    Fatvalid(input)
                }
            }

        }
    }
    return nil
}

And now i really want to learn how to change this bit:

if slice, ok := el.Interface().([]*Child); ok {
    for _, input := range slice {
        Fatvalid(input)
    }
}

...so that i don't have to hardcode cast of the type on the interface like that ([]*Child) but to use the reflection to do that for me. Is this possible?

I know that the whole idea of doing a validation this way looks strange but i really need to have it this way because otherwise it complicates so many other things.





Aucun commentaire:

Enregistrer un commentaire