将接口{}转换为在运行时类型中计算

时间:2016-11-30 12:21:07

标签: go

以下是我需要的示意图:

func decode(data []byte, target interface{}) (interface{}, error) {
    decoded := target.(reflect.TypeOf(target)) // pseudocode
    err := json.Unmarshal(data, &decoded)
    ...

我在SO上发现了几个类似的问题,但所有解决方案都是关于target.(type)的转换。这不是我寻找的最佳解决方案。

我也找到了带反射的解决方案:

decoded := reflect.ValueOf(target).Convert(reflect.TypeOf(target))
// fmt.Printf("%T", decoded) == reflect.Value

但我无法理解如何从reflect.Value获取结构以将其传递给json.Unmarshal函数。

如何使用此decode功能?

我在不同的结构中有多个请求。我可以确定应该使用什么结构来解码请求。我在请求类型和结构之间进行映射,如map[RequestMethod]interface{}

原理图版本如下所示:

func hydrate(data []byte) (interface{}, error) {
    var base baseResponse

    if err := json.Unmarshal(data, &base); err != nil {
        return nil, err
    }

    target, ok := methodsMap[Method(base.Method)]

    if !ok {
        return nil, errors.New("Trying to hydrate data with unknown method: " + base.Method)
    }

    decoded, err := decode(data, target) // Expected target type.

添加了:

如果我们将target传递给json.Unmarshal而不转换为类型,我们将获得map。例如:

func decode(data []byte, target interface{}) (interface{}, error) {
    err := json.Unmarshal(data, &target)
    // fmt.Printf("%T", target) == map[string]interface{} not struct.

解决方案

感谢@icza我们找到了解决方案:

func hydrate(data [] byte)(interface {},error){         var base baseResponse

    if err := json.Unmarshal(data, &base); err != nil {
        return nil, err
    }

    target, ok := methodsMap[Method(base.Method)]

    if !ok {
        return nil, errors.New("Trying to hydrate data with unknown method: " + base.Method)
    }

    // Clone request draft struct.
    decoded := reflect.New(reflect.ValueOf(target).Type()).Interface()
    err := decode(data, decoded)
    ...

相关链接:

Golang interface{} type misunderstanding

How to copy an interface value in Go?

1 个答案:

答案 0 :(得分:4)

使用以下代码创建草稿结构的副本并对其进行解组:

t := reflect.TypeOf(methodsMap[Method(base.Method)])
pv := reflect.New(t)
err := json.Unmarshal(p, pv.Interface())
return pv.Elem().Interface(), err  // pv.Elem() dereferences ptr 

playground example