Skip to content

Instantly share code, notes, and snippets.

@yaxinr
Last active June 28, 2022 19:32
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save yaxinr/679976f1cde2a7b2925c30fa89b03eea to your computer and use it in GitHub Desktop.
Save yaxinr/679976f1cde2a7b2925c30fa89b03eea to your computer and use it in GitHub Desktop.
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