Call a Struct and its Method by name in Go?

后端 未结 4 680
我在风中等你
我在风中等你 2020-12-02 05:47

I have found a function call MethodByName() here http://golang.org/pkg/reflect/#Value.MethodByName but it\'s not exactly what I want! (maybe because I don\'t kn

4条回答
  •  南方客
    南方客 (楼主)
    2020-12-02 06:24

    gist invoke struct method with error handling

    // 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
    }
    

提交回复
热议问题