Golang 得到反射调用的结果

Zan*_*r17 4 reflection go

我正在调用反射函数,但目前我一直在尝试获取返回值。

示例代码:

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
}
Run Code Online (Sandbox Code Playgroud)

如何从“value”获取返回值并正确返回它们?

干杯

icz*_*cza 6

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

就像在这个简化的例子中一样:

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
}
Run Code Online (Sandbox Code Playgroud)

测试它:

result, err := Send("test", "testData")
fmt.Println(result, err)
Run Code Online (Sandbox Code Playgroud)

输出:

test-result-data:testData test-error
Run Code Online (Sandbox Code Playgroud)

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

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

测试它:

result, err = Send2("test", "testData")
fmt.Println(result, err)
Run Code Online (Sandbox Code Playgroud)

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