为了账号安全,请及时绑定邮箱和手机立即绑定

从通用且以某种方式动态的 go 地图获取内容的最佳方式是什么?

从通用且以某种方式动态的 go 地图获取内容的最佳方式是什么?

Go
斯蒂芬大帝 2022-06-13 16:16:19
我有这个 json 可以转换为:var leerCHAT []interface{}但是我正在经历疯狂的箍来到达地图内部和地图内部疯狂的地图上的任何点,特别是因为有些结果是不同的内容。这是Json[   null,   null,   "hub:zWXroom",   "presence_diff",   {      "joins":{         "f718a187-6e96-4d62-9c2d-67aedea00000":{            "metas":[               {                  "context":{},                  "permissions":{},                  "phx_ref":"zNDwmfsome=",                  "phx_ref_prev":"zDMbRTmsome=",                  "presence":"lobby",                  "profile":{},                  "roles":{}               }            ]         }      },      "leaves":{}   }]我需要进入配置文件,然后里面有一个“DisplayName”字段。所以我一直在做疯狂的黑客攻击..即使这样我也被卡住了一半......首先是一个数组,所以我可以做一些事情[elementnumber] 然后是当棘手的映射开始时......对所有打印等感到抱歉,是为了调试并查看我要返回的元素数量。if leerCHAT[3] == "presence_diff" {                var id string                presence := leerCHAT[4].(map[string]interface{})                log.Printf("algo: %v", len(presence))                log.Printf("algo: %s", presence["joins"])                vamos := presence["joins"].(map[string]interface{})                for i := range vamos {                    log.Println(i)                    id = i                }                log.Println(len(vamos))                vamonos := vamos[id].(map[string]interface{})                log.Println(vamonos)                log.Println(len(vamonos))                metas := vamonos["profile"].(map[string]interface{})   \\\ I get error here..                log.Println(len(metas))            }到目前为止,我可以一直看到 meta:{...} 但无法继续将我的 hacky 代码用于我需要的内容。注意:因为在 Joins: 和 metas: 之前的 id 是动态的,所以我必须以某种方式获取它,因为它始终只是一个元素,我做了 for range 循环来抓取它。
查看完整描述

1 回答

?
弑天下

TA贡献1818条经验 获得超8个赞

索引 3 处的数组元素描述了索引 4 处的变体 JSON 的类型。


以下是如何将 JSON 解码为 Go 值。首先,为 JSON 的每个变体部分声明 Go 类型:


type PrescenceDiff struct {

     Joins map[string]*Presence // declaration of Presence type to be supplied

     Leaves map[string]*Presence

}


type Message struct {

     Body string

}

声明一个将类型字符串与 Go 类型相关联的映射:


var messageTypes = map[string]reflect.Type{

    "presence_diff": reflect.TypeOf(&PresenceDiff{}),

    "message":       reflect.TypeOf(&Message{}),

    // add more types here as needed

}

将变体部分解码为原始消息。使用索引 3 处的元素中的名称来创建适当 Go 类型的值并解码为该值:


func decode(data []byte) (interface{}, error) {

    var messageType string

    var raw json.RawMessage

    v := []interface{}{nil, nil, nil, &messageType, &raw}

    err := json.Unmarshal(data, &v)

    if err != nil {

        return nil, err

    }


    if len(raw) == 0 {

        return nil, errors.New("no message")

    }


    t := messageTypes[messageType]

    if t == nil {

        return nil, fmt.Errorf("unknown message type: %q", messageType)

    }


    result := reflect.New(t.Elem()).Interface()

    err = json.Unmarshal(raw, result)

    return result, err

}

使用类型开关访问消息的变体部分:


defer ws.Close()


for {

    _, data, err := ws.ReadMessage()

    if err != nil {

        log.Printf("Read error: %v", err)

        break

    }


    v, err := decode(data)

    if err != nil {

        log.Printf("Decode error: %v", err)

        continue

    }


    switch v := v.(type) {

    case *PresenceDiff:

        fmt.Println(v.Joins, v.Leaves)

    case *Message:

        fmt.Println(v.Body)

    default:

        fmt.Printf("type %T not handled\n", v)

    }

}


查看完整回答
反对 回复 2022-06-13
  • 1 回答
  • 0 关注
  • 115 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号