2017-10-06 126 views
2

我正在进行反射函数调用,但我目前一直试图获取返回值。Golang获得反射调用的结果

示例代码:

func (c *Client) Send(funcName protoFunction, data interface{}) (interface{}, error) { 
    funcList := c.GetProtoFuncList() 
    ctx := context.Background() 
    f := reflect.ValueOf(funcList[funcName.String()]) 
    vals := make([]reflect.Value, 2) 
    vals[0] = reflect.ValueOf(ctx) 
    vals[1] = reflect.ValueOf(data) 
    value := f.Call(vals) 
    log.Debug(value) 
    return nil, nil 
} 

我如何从“价值”的返回值和返回正确呢?

干杯

+0

你得到它们。代码中的'value'将是返回值的一部分。你有什么问题? – Adrian

+0

如果您查看['Call'签名](https://golang.org/pkg/reflect/#Value.Call),您的'value'是'[] reflect.Value'。你甚至可以打印出来。究竟是什么问题? – JimB

+1

想知道,为什么你使用反射,为什么不直接调用它,并返回结果,例如'funcName.String()]。(func(context.Context,interface {}))(interface {},error))(ctx,data)'' (只有在'funcList'中存储不同类型的函数时才需要类型断言;否则,您甚至可以摆脱它,并且它变为'return funcList [funcName.String()](ctx,data)'。) – icza

回答

2

Value.Call()返回函数调用为[]reflect.Value的返回值。您可以使用Value.Interface()方法将reflect.Value表示的值作为interface{}的值。从那里,您可以使用type assertion来获取不同类型的值。

像该简化的例子:

var funcList = map[string]interface{}{ 
    "test": func(ctx context.Context, data interface{}) (interface{}, error) { 
     return "test-result-data:" + fmt.Sprint(data), errors.New("test-error") 
    }, 
} 

func Send(funcName string, data interface{}) (interface{}, error) { 
    f := reflect.ValueOf(funcList[funcName]) 
    params := []reflect.Value{ 
     reflect.ValueOf(context.Background()), 
     reflect.ValueOf(data), 
    } 
    res := f.Call(params) 

    ret := res[0].Interface() 
    var err error 
    if v := res[1].Interface(); v != nil { 
     err = v.(error) 
    } 
    return ret, err 
} 

测试它:

result, err := Send("test", "testData") 
fmt.Println(result, err) 

输出:

test-result-data:testData test-error 

但是,这是不必要的复杂。你并不需要使用反射来调用一个函数,你可以直接调用它,并将结果直接返回,这样的:

func Send2(funcName string, data interface{}) (interface{}, error) { 
    return funcList[funcName].(func(context.Context, interface{}) (interface{}, error))(
     context.Background(), data, 
    ) 
} 

测试它:

result, err = Send2("test", "testData") 
fmt.Println(result, err) 

输出是一样的。试试Go Playground上的示例。

+0

谢谢你的明确回应。这正是我所需要的。 – Zander17