Search code examples
gomethodsstructreflectiontype-switch

Calling interface method after reflection & type switching in golang


I have struct

type ChartOpts struct {
    Name              mypakage.MyType
    Repo              mypakage.MyType
}

Ι want to iterate over its fields and if a type assertion is satisfied, called the method on that (asserted) type.

func (chartOpts ChartOpts) BindFlags(cobCom *cobra.Command) {
    fields := reflect.TypeOf(chartOpts)
    values := reflect.ValueOf(chartOpts)
    num := fields.NumField()
    fmt.Println(fields, values, num)
    for i := 0; i < num; i++ {
        field := fields.Field(i)
        switch v := field.Type.(type) {
        case mypackage.MyType:
            field.BindPersistentFlag(cobCom)
        default:
            log.Fatal(ErrUnhandledType)
        }
    }
    

}

The above code does not compile with this error:

field.BindPersistentFlag undefined (type reflect.StructField has no field or method BindPersistentFlag)

why?


Solution

  • field is of type reflect.StructField, it's not the field's value, it is its struct field descriptor.

    You need to type-switch on the field's value:

    values.Field(i)
    

    Note that the above is the field's value wrapped in reflect.Value, so extract the value with Value.Interface():

    for i := 0; i < num; i++ {
        switch v := values.Field(i).Interface().(type) {
        case mypackage.MyType:
            v.BindPersistentFlag(cobCom)
        default:
            log.Fatal(ErrUnhandledType)
        }
    }
    

    And call BindPersistentFlag() on v, as that will be of type mypackage.MyType inside the case.