首页 文章

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

提问于
浏览
1

这是我需要的示意图:

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 获取struct以将其传递给 json.Unmarshal 函数 .

How this decode function will be used?

我有不同结构的多个请求 . 我可以确定我应该使用什么结构来解码请求 . 我在请求类型和结构之间进行映射,如 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.

Solution

感谢@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 回答

  • 3

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

    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

相关问题