in internal/kernel/callbacks.go [199:257]
func (c *Client) invoke(method reflect.Value, args []interface{}) (retval reflect.Value, err error) {
if !method.IsValid() {
err = fmt.Errorf("invalid method")
return
}
// Convert the arguments, if any...
callArgs := make([]reflect.Value, len(args))
methodType := method.Type()
numIn := methodType.NumIn()
for i, arg := range args {
var argType reflect.Type
if i < numIn {
argType = methodType.In(i)
} else if methodType.IsVariadic() {
argType = methodType.In(i - 1)
} else {
err = fmt.Errorf("too many arguments received %d for %d", len(args), numIn)
return
}
if argType.Kind() == reflect.Ptr {
callArgs[i] = reflect.New(argType.Elem())
} else {
callArgs[i] = reflect.New(argType)
}
c.castAndSetToPtr(callArgs[i].Elem(), reflect.ValueOf(arg))
if argType.Kind() != reflect.Ptr {
// The result of `reflect.New` is always a pointer, so if the
// argument is by-value, we have to de-reference it first.
callArgs[i] = callArgs[i].Elem()
}
}
// Ready to catch an error if the method panics...
defer func() {
if r := recover(); r != nil {
if err == nil {
var ok bool
if err, ok = r.(error); !ok {
err = fmt.Errorf("%v", r)
}
} else {
// This is not expected - so we panic!
panic(r)
}
}
}()
result := method.Call(callArgs)
switch len(result) {
case 0:
// Nothing to do, retval is already a 0-value.
case 1:
retval = result[0]
default:
err = fmt.Errorf("too many return values: %v", result)
}
return
}