获取Golang反射调用的结果

5
我正在进行一个反射函数调用,但我目前困在尝试获取返回值的过程中。
示例代码:
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
}

如何正确获取“值”的返回值并将其返回?
谢谢。

你已经得到它们了。在你的代码中,value将是返回值的一个切片。你遇到了什么问题? - Adrian
如果您查看Call签名,您的value是一个[]reflect.Value。您甚至打印了这个。问题到底是什么? - JimB
1
只是好奇,为什么你使用反射?为什么不直接调用并返回结果,例如return funcList[funcName.String()].(func(context.Context, interface{})) (interface{}, error)) (ctx, data)?(如果存储在funcList中的函数类型相同,则不需要类型断言甚至可以将其摆脱,变成return funcList[funcName.String()](ctx, data)。) - icza
返回类型是Value类型,但我想使用send()函数返回类型为interface{}和error的被调用值。如何将[]Value中的error强制转换为error类型? - Zander17
1个回答

7

Value.Call() 方法返回函数调用的返回值,类型为 []reflect.Value。您可以使用 Value.Interface() 方法将 reflect.Value 表示的值转换为 interface{} 类型。然后,您可以使用类型断言来获取不同类型的值。

例如,在以下简化示例中:

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上尝试这些示例。


谢谢您清晰的回答。这正是我所需要的。 - Zander17

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接