invoke(call) struct method in golang
package myreflect | |
import ( | |
"fmt" | |
"reflect" | |
) | |
// Invoke - firstResult, err := invoke(AnyStructInterface, MethodName, Params...) | |
func Invoke(any interface{}, name string, args ...interface{}) (reflect.Value, error) { | |
method := reflect.ValueOf(any).MethodByName(name) | |
methodType := method.Type() | |
numIn := methodType.NumIn() | |
if numIn > len(args) { | |
return reflect.ValueOf(nil), fmt.Errorf("Method %s must have minimum %d params. Have %d", name, numIn, len(args)) | |
} | |
if numIn != len(args) && !methodType.IsVariadic(){ | |
return reflect.ValueOf(nil), fmt.Errorf("Method %s must have %d params. Have %d", name, numIn, len(args)) | |
} | |
in := make([]reflect.Value, len(args)) | |
for i := 0; i < len(args); i++ { | |
var inType reflect.Type | |
if methodType.IsVariadic() && i >= numIn-1 { | |
inType = methodType.In(numIn - 1).Elem() | |
} else { | |
inType = methodType.In(i) | |
} | |
argValue := reflect.ValueOf(args[i]) | |
if !argValue.IsValid() { | |
return reflect.ValueOf(nil), fmt.Errorf("Method %s. Param[%d] must be %s. Have %s", name, i, inType, argValue.String()) | |
} | |
argType := argValue.Type() | |
if argType.ConvertibleTo(inType) { | |
in[i] = argValue.Convert(inType) | |
} else { | |
return reflect.ValueOf(nil), fmt.Errorf("Method %s. Param[%d] must be %s. Have %s", name, i, inType, argType) | |
} | |
} | |
return method.Call(in)[0], nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment