doubo82706 2016-11-30 12:21
浏览 70
已采纳

将接口{}强制转换为运行时类型

Here is schematic example what I need:

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

I found several similar questions on SO, but all solutions are about switch by target.(type). This is not the best solution what I look for.

Also I found solution with reflection:

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

But I couldn't understand how to get struct from reflect.Value to pass it to json.Unmarshal function.

How this decode function will be used?

I have multiple requests in different structures. I can determine what struct I should use to decode request. I have mapping between request type and structure like this map[RequestMethod]interface{}.

Schematic version looks like this:

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.

Added:

If we pass our target to json.Unmarshal without casting to it type we will obtain map. Example:

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

Solution

Thanks to @icza we found solution:

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)
    ...

Related links:

Golang interface{} type misunderstanding

How to copy an interface value in Go?

  • 写回答

1条回答 默认 最新

  • doubaolan2842 2016-11-30 13:49
    关注

    Use the following code to create a copy of the draft struct and unmarshal to it:

    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

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 如何让企业微信机器人实现消息汇总整合
  • ¥50 关于#ui#的问题:做yolov8的ui界面出现的问题
  • ¥15 如何用Python爬取各高校教师公开的教育和工作经历
  • ¥15 TLE9879QXA40 电机驱动
  • ¥20 对于工程问题的非线性数学模型进行线性化
  • ¥15 Mirare PLUS 进行密钥认证?(详解)
  • ¥15 物体双站RCS和其组成阵列后的双站RCS关系验证
  • ¥20 想用ollama做一个自己的AI数据库
  • ¥15 关于qualoth编辑及缝合服装领子的问题解决方案探寻
  • ¥15 请问怎么才能复现这样的图呀