func()

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
}