【问题标题】:Golang getting the result of a reflection callGolang 得到反射调用的结果
【发布时间】:2017-10-06 22:19:12
【问题描述】:

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

示例代码:

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”中获取返回值并正确返回?

干杯

【问题讨论】:

  • 你得到它们了。您的代码中的value 将是返回值的一部分。你遇到了什么问题?
  • 如果您查看Call signature,您的value[]reflect.Value。你甚至打印出来。究竟是什么问题?
  • 只是想知道,为什么要使用反射,为什么不直接调用它,并返回结果,例如return funcList[funcName.String()].(func(context.Context, interface{})) (interface{}, error)) (ctx, data)? (只有在funcList中存储了不同类型的函数时才需要类型断言;如果没有,你甚至可以去掉它,它变成return funcList[funcName.String()](ctx, data)。)
  • 返回类型是 Value 类型,但是我会使用 send() 函数将调用的值作为 interface{} 类型返回,错误。如何将 []Value 中的错误类型转换为错误类型?

标签: go reflection


【解决方案1】:

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 上的示例。

【讨论】:

  • 感谢您的明确答复。这正是我所需要的。
猜你喜欢
  • 2022-01-24
  • 2016-08-07
  • 1970-01-01
  • 2015-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多