func typeString_FuncOrMethod( name string, t reflect.Type, pkgPath string) (s string) { // Deal with input types. var in []string for i := 0; i < t.NumIn(); i++ { in = append(in, typeString(t.In(i), pkgPath)) } // And output types. var out []string for i := 0; i < t.NumOut(); i++ { out = append(out, typeString(t.Out(i), pkgPath)) } // Put it all together. s = fmt.Sprintf( "%s(%s) (%s)", name, strings.Join(in, ", "), strings.Join(out, ", ")) return }
func OutTypes(fnType reflect.Type) []reflect.Type { var types []reflect.Type for i := 0; i < fnType.NumOut(); i++ { types = append(types, fnType.Out(i)) } return types }
// Note: Methods take the receiver as the first argument, which the want // signature doesn't include. func sigMatches(got, want reflect.Type) bool { nin := want.NumIn() if got.NumIn()-1 != nin { return false } nout := want.NumOut() if got.NumOut() != nout { return false } for i := 0; i < nin; i++ { if got.In(i+1) != want.In(i) { return false } } for i := 0; i < nout; i++ { if got.Out(i) != want.Out(i) { return false } } return true }
// Add all necessary imports for the type, recursing as appropriate. func addImportsForType(imports importMap, t reflect.Type) { // Add any import needed for the type itself. addImportForType(imports, t) // Handle special cases where recursion is needed. switch t.Kind() { case reflect.Array, reflect.Chan, reflect.Ptr, reflect.Slice: addImportsForType(imports, t.Elem()) case reflect.Func: // Input parameters. for i := 0; i < t.NumIn(); i++ { addImportsForType(imports, t.In(i)) } // Return values. for i := 0; i < t.NumOut(); i++ { addImportsForType(imports, t.Out(i)) } case reflect.Map: addImportsForType(imports, t.Key()) addImportsForType(imports, t.Elem()) } }
// Verifies whether a conversion function has a correct signature. func verifyConversionFunctionSignature(ft reflect.Type) error { if ft.Kind() != reflect.Func { return fmt.Errorf("expected func, got: %v", ft) } if ft.NumIn() != 3 { return fmt.Errorf("expected three 'in' params, got: %v", ft) } if ft.NumOut() != 1 { return fmt.Errorf("expected one 'out' param, got: %v", ft) } if ft.In(0).Kind() != reflect.Ptr { return fmt.Errorf("expected pointer arg for 'in' param 0, got: %v", ft) } if ft.In(1).Kind() != reflect.Ptr { return fmt.Errorf("expected pointer arg for 'in' param 1, got: %v", ft) } scopeType := Scope(nil) if e, a := reflect.TypeOf(&scopeType).Elem(), ft.In(2); e != a { return fmt.Errorf("expected '%v' arg for 'in' param 2, got '%v' (%v)", e, a, ft) } var forErrorType error // This convolution is necessary, otherwise TypeOf picks up on the fact // that forErrorType is nil. errorType := reflect.TypeOf(&forErrorType).Elem() if ft.Out(0) != errorType { return fmt.Errorf("expected error return, got: %v", ft) } return nil }
func newTypeFromFactoryFunction(function interface{}, factoryType reflect.Type, parameters []interface{}) TypeFactory { if factoryType.NumOut() != 1 { return newInvalidType(fmt.Errorf("invalid number of return parameters: %d", factoryType.NumOut())) } kindOfGeneratedType := factoryType.Out(0).Kind() if kindOfGeneratedType != reflect.Interface && kindOfGeneratedType != reflect.Ptr { return newInvalidType(fmt.Errorf("return parameter is no interface or pointer but a %v", kindOfGeneratedType)) } if factoryType.IsVariadic() { if factoryType.NumIn() > len(parameters) { return newInvalidType(fmt.Errorf("invalid number of input parameters for variadic function: got %d but expected at least %d", len(parameters), factoryType.NumIn())) } } else { if factoryType.NumIn() != len(parameters) { return newInvalidType(fmt.Errorf("invalid number of input parameters: got %d but expected %d", len(parameters), factoryType.NumIn())) } } t := &typeFactory{ factory: reflect.ValueOf(function), factoryType: factoryType, } var err error t.factoryArguments, err = buildFactoryCallArguments(factoryType, parameters) if err != nil { return newInvalidType(err) } return t }
// verifyHandler ensures that the given t is a function with the following signature: // func(json.Context, *ArgType)(*ResType, error) func verifyHandler(t reflect.Type) error { if t.NumIn() != 2 || t.NumOut() != 2 { return fmt.Errorf("handler should be of format func(json.Context, *ArgType) (*ResType, error)") } isStructPtr := func(t reflect.Type) bool { return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct } isMap := func(t reflect.Type) bool { return t.Kind() == reflect.Map && t.Key().Kind() == reflect.String } validateArgRes := func(t reflect.Type, name string) error { if !isStructPtr(t) && !isMap(t) { return fmt.Errorf("%v should be a pointer to a struct, or a map[string]interface{}", name) } return nil } if t.In(0) != typeOfContext { return fmt.Errorf("arg0 should be of type json.Context") } if err := validateArgRes(t.In(1), "second argument"); err != nil { return err } if err := validateArgRes(t.Out(0), "first return value"); err != nil { return err } if !t.Out(1).AssignableTo(typeOfError) { return fmt.Errorf("second return value should be an error") } return nil }
func checkFunc(fnType reflect.Type) (bool, error) { var state State foundState := 0 nin := fnType.NumIn() for i := 0; i < nin; i++ { if fnType.In(i) == reflect.TypeOf(state) { foundState++ } else if fnType.In(i) == reflect.TypeOf(&state) { return false, fmt.Errorf("raw function can not use `*State' as arg, instead using `State'") } } wrongRawFunc := false if foundState > 1 { wrongRawFunc = true } else if foundState == 1 { nout := fnType.NumOut() if nin != 1 || nout != 1 { wrongRawFunc = true } else { if fnType.Out(0).Kind() != reflect.Int { wrongRawFunc = true } } } if wrongRawFunc { return false, fmt.Errorf("raw function must be type: `func(State) int'") } return true, nil }
func makeClosure(fv reflect.Value, ft reflect.Type) *function { fn := &function{ call: fv, } var rt = Void var at []Type if n := ft.NumOut(); n != 0 { rt = makeRetType(reflect.New(ft.Out(0))) } if n := ft.NumIn(); n != 0 { at = make([]Type, n) for i := 0; i != n; i++ { at[i] = makeArgType(reflect.Zero(ft.In(i))) } } fn.Interface = Prepare(rt, at...) if err := constructClosure(fn); err != nil { panic(err) } runtime.SetFinalizer(fn, destroyClosure) return fn }
func methSigMatches(got reflect.Type, _want interface{}) error { // Note: Methods take the receiver as the first argument, which the want // signature doesn't include. if got.NumIn() == 0 { // The receiver is missing! return fmt.Errorf("Method without reciever!") } want := reflect.TypeOf(_want) if got.NumIn()-1 != want.NumIn() { return fmt.Errorf("Method should have %d arguments, not %d", want.NumIn(), got.NumIn()-1) } if got.NumOut() != want.NumOut() { return fmt.Errorf("Method should have %d return values, not %d", want.NumOut(), got.NumOut()) } for i := 0; i < want.NumIn(); i++ { if got.In(i+1) != want.In(i) { return fmt.Errorf("Method argument %d should be %v, not %v", i+1, want.In(i), got.In(i+1)) } } for i := 0; i < want.NumOut(); i++ { if got.Out(i) != want.Out(i) { return fmt.Errorf("Method return value %d should be %v, not %v", i+1, want.Out(i), got.Out(i)) } } return nil }
func FormatFuncArguments(t reflect.Type) (decl string) { decl = "(" in := make([]string, t.NumIn()) for i := range in { in[i] = ValType(t.In(i)) } decl += strings.Join(in, ",") + ")" out := make([]string, t.NumOut()) if len(out) > 0 { for i := range out { out[i] = ValType(t.Out(i)) } s := strings.Join(out, ",") if len(out) != 1 { s = "(" + s + ")" } decl += " " + s } return }
func hasLastError(t reflect.Type) bool { N := t.NumOut() if N == 0 { return false } return t.Out(N-1) == errorType }
// Verifies whether a deep-copy function has a correct signature. func verifyDeepCopyFunctionSignature(ft reflect.Type) error { if ft.Kind() != reflect.Func { return fmt.Errorf("expected func, got: %v", ft) } if ft.NumIn() != 3 { return fmt.Errorf("expected three 'in' params, got $v", ft) } if ft.NumOut() != 1 { return fmt.Errorf("expected one 'out' param, got %v", ft) } if ft.In(1).Kind() != reflect.Ptr { return fmt.Errorf("expected pointer arg for 'in' param 1, got: %v", ft) } if ft.In(1).Elem() != ft.In(0) { return fmt.Errorf("expected 'in' param 0 the same as param 1, got: %v", ft) } var forClonerType Cloner if expected := reflect.TypeOf(&forClonerType); ft.In(2) != expected { return fmt.Errorf("expected '%v' arg for 'in' param 2, got: '%v'", expected, ft.In(2)) } var forErrorType error // This convolution is necessary, otherwise TypeOf picks up on the fact // that forErrorType is nil errorType := reflect.TypeOf(&forErrorType).Elem() if ft.Out(0) != errorType { return fmt.Errorf("expected error return, got: %v", ft) } return nil }
func (ms *GobMarshaller) Prepare(name string, fn interface{}) (err error) { var ( fT reflect.Type ) // Gob needs to register type before encode/decode if fT = reflect.TypeOf(fn); fT.Kind() != reflect.Func { err = fmt.Errorf("fn is not a function but %v", fn) return } reg := func(v reflect.Value) (err error) { if !v.CanInterface() { err = fmt.Errorf("Can't convert to value in input of %v for name:%v", fn, name) return } gob.Register(v.Interface()) return } for i := 0; i < fT.NumIn(); i++ { // create a zero value of the type of parameters if err = reg(reflect.Zero(fT.In(i))); err != nil { return } } for i := 0; i < fT.NumOut(); i++ { if err = reg(reflect.Zero(fT.Out(i))); err != nil { return } } return }
func returns(f reflect.Type) []reflect.Type { out := make([]reflect.Type, f.NumOut()) for i := 0; i < f.NumOut(); i++ { out[i] = f.Out(i) } return out }
// A version of Invoke that does error checking, used by both public methods. func (a *returnAction) buildInvokeResult( sig reflect.Type) (res []interface{}, err error) { // Check the length of the return value. numOut := sig.NumOut() numVals := len(a.returnVals) if numOut != numVals { err = errors.New( fmt.Sprintf("Return given %d vals; expected %d.", numVals, numOut)) return } // Attempt to coerce each return value. res = make([]interface{}, numOut) for i, val := range a.returnVals { resType := sig.Out(i) res[i], err = a.coerce(val, resType) if err != nil { res = nil err = errors.New(fmt.Sprintf("Return: arg %d: %v", i, err)) return } } return }
// t's Kind must be a reflect.Func. func funcArgsFromType(t reflect.Type) (in []*Parameter, variadic *Parameter, out []*Parameter, err error) { nin := t.NumIn() if t.IsVariadic() { nin-- } var p *Parameter for i := 0; i < nin; i++ { p, err = parameterFromType(t.In(i)) if err != nil { return } in = append(in, p) } if t.IsVariadic() { p, err = parameterFromType(t.In(nin).Elem()) if err != nil { return } variadic = p } for i := 0; i < t.NumOut(); i++ { p, err = parameterFromType(t.Out(i)) if err != nil { return } out = append(out, p) } return }
func function2Func(in *reflect.Value, t reflect.Type) { fn := in.MethodByName("Call") wrap := func(args []reflect.Value) (results []reflect.Value) { ret := fn.Call(args)[0] n := t.NumOut() if n == 0 { return } if n == 1 { if t.Out(0) != typeIntf { ret = ret.Elem() } return []reflect.Value{ret} } if ret.Kind() != reflect.Slice || ret.Len() != n { panic(fmt.Sprintf("unexpected return value count, we need `%d` values", n)) } results = make([]reflect.Value, n) for i := 0; i < n; i++ { result := ret.Index(i) if t.Out(i) != typeIntf { result = result.Elem() } results[i] = result } return } *in = reflect.MakeFunc(t, wrap) }
func getMethod(methodType reflect.Type, fn reflect.Value) *methodWrapper { if methodType.NumOut() != 1 { return nil } if methodType.Out(0) != typeOfError { return nil } if methodType.NumIn() == 2 { // Method needs two ins: receiver, *Conn. if methodType.In(1) != typeOfConn { return nil } return &methodWrapper{plain: true, fn: fn} } if methodType.NumIn() == 4 { // Method needs four ins: receiver, *Conn, request, *reply. if methodType.In(1) != typeOfConn { return nil } if methodType.In(3).Kind() != reflect.Ptr { return nil } return &methodWrapper{ plain: false, fn: fn, requestType: methodType.In(2), responseType: methodType.In(3).Elem()} } return nil }
func funcIsBypass(t reflect.Type) bool { if t.NumIn() == 1 && t.NumOut() == 1 && t.In(0) == refTypeLStatePtr && t.Out(0) == refTypeInt { return true } if t.NumIn() == 2 && t.NumOut() == 1 && t.In(1) == refTypeLStatePtr && t.Out(0) == refTypeInt { return true } return false }
func goodFunc(typ reflect.Type) bool { switch { case typ.NumOut() == 1: return true case typ.NumOut() == 2 && typ.Out(1) == rferrorType: return true } return false }
func getOutputs(ft reflect.Type) []reflect.Type { numOut := ft.NumOut() outputs := make([]reflect.Type, numOut) for i := 0; i < numOut; i++ { outputs[i] = ft.Out(i) } return outputs }
func (f *FuncUtil) getReturnTypes(t reflect.Type) []reflect.Type { if t.NumOut() == 0 { return nil } rets := []reflect.Type{} for i := 0; i < t.NumOut(); i++ { rets = append(rets, t.Out(i)) } return rets }
// goodFunc reports whether the function or method has the right result signature. func goodFunc(typ reflect.Type) bool { // We allow functions with 1 result or 2 results where the second is an error. switch { case typ.NumOut() == 1: return true case typ.NumOut() == 2 && typ.Out(1) == errorType: return true } return false }
// isPubSub tests whether the given method has as as first argument a context.Context // and returns the pair (Subscription, error) func isPubSub(methodType reflect.Type) bool { // numIn(0) is the receiver type if methodType.NumIn() < 2 || methodType.NumOut() != 2 { return false } return isContextType(methodType.In(1)) && isSubscriptionType(methodType.Out(0)) && isErrorType(methodType.Out(1)) }
func functionArgRetTypes(funt reflect.Type) (targs, tout []reflect.Type) { targs = make([]reflect.Type, funt.NumIn()) for i := range targs { targs[i] = funt.In(i) } tout = make([]reflect.Type, funt.NumOut()) for i := range tout { tout[i] = funt.Out(i) } return }
// makeZeroReturnValues creates a []interface{} containing appropriate zero // values for returning from the supplied method type. func makeZeroReturnValues(signature reflect.Type) []interface{} { result := make([]interface{}, signature.NumOut()) for i, _ := range result { outType := signature.Out(i) zeroVal := reflect.Zero(outType) result[i] = zeroVal.Interface() } return result }
func assertValidFetcher(t reflect.Type) { if t.Kind() != reflect.Func { panic(fmt.Sprintf("rcache: Fetcher must be a function, got [%v]", t)) } if t.NumIn() != 1 { panic(fmt.Sprintf("rcache: Fetcher must be function with one arg, has %d [%v]", t.NumIn(), t)) } if t.NumOut() != 2 || t.Out(0) != byteArrayType || t.Out(1) != errorType { panic(fmt.Sprintf("rcache: Fetcher must be function that returns ([]byte, error), has %d [%v]", t.NumOut(), t)) } }
// ForeachResult 遍历instance所有返回值,instance必须是函数类型 func ForeachResult(instance reflect.Type, solve func(result reflect.Type) error) error { if instance.Kind() == reflect.Func { for i := 0; i < instance.NumOut(); i++ { var err = solve(instance.Out(i)) if err != nil { return err } } return nil } return ErrorParamNotFunc.Format(instance.String()).Error() }
func checkFunctionSignatureNums(t reflect.Type, args, results int) error { if t.Kind() != reflect.Func { return fmt.Errorf("Expected a function but got a %s", t) } if t.NumIn() != args { return fmt.Errorf("Expected %d function arguments, got %d", args, t.NumIn()) } if t.NumOut() != results { return fmt.Errorf("Expected %d function results, got %d", results, t.NumOut()) } return nil }