简体   繁体   English

Go:键入地图断言

[英]Go: type assertion for maps

I'm reading data structures from JSON. 我正在从JSON读取数据结构。 There's a little bit of conversions going on and at the end I have a struct where one of the fields is of type interface{} . 有一些转换正在进行,最后我有一个struct ,其中一个字段是interface{}类型。 It's actually a map, so JSON puts it inside a map[string]inteface{} . 它实际上是一个地图,所以JSON将它放在一个map[string]inteface{}

I actually know that the underlying structure is map[string]float64 and I would like to use it like that, so I try to do an assertion. 我实际上知道底层结构是map[string]float64 ,我想这样使用它,所以我尝试做一个断言。 The following code reproduces the behaviour: 以下代码重现了该行为:

type T interface{}

func jsonMap() T {
    result := map[string]interface{}{
        "test": 1.2,
    }
    return T(result)
}

func main() {
    res := jsonMap()

    myMap := res.(map[string]float64)

    fmt.Println(myMap)
}

I get the error: 我收到错误:

panic: interface conversion: main.T is map[string]interface {}, not map[string]float64

I can do the following: 我可以做以下事情:

func main() {
    // A first assertion
    res := jsonMap().(map[string]interface{})

    myMap := map[string]float64{
        "test": res["test"].(float64), // A second assertion
    }

    fmt.Println(myMap)
}

This works fine, but I find it very ugly since I need to reconstruct the whole map and use two assertions. 这工作正常,但我发现它非常难看,因为我需要重建整个地图并使用两个断言。 Is there a correct way to force the first assertion to drop the interface{} and use float64 ? 是否有正确的方法强制第一个断言删除interface{}并使用float64 In other words, what is the correct way to do the original assertion .(map[string]float64) ? 换句话说,执行原始断言的正确方法是什么.(map[string]float64)

Edit: 编辑:

The actual data I'm parsing looks like this: 我正在解析的实际数据如下所示:

[
 {"Type":"pos",
 "Content":{"x":0.5 , y: 0.3}} ,

{"Type":"vel",
"Content":{"vx": 0.1, "vy": -0.2}}
]

In Go I use a struct and encoding/json in the following way. 在Go中,我使用structencoding/json以下列方式。

type data struct {
    Type string
    Content interface{}
}

// I read the JSON from a WebSocket connection
_, event, _ := c.ws.ReadMessage()

j := make([]data,0)
json.Unmarshal(event, &j)

You cannot type assert map[string]interface{} to map[string]float64 . 您不能键入assert map[string]interface{}map[string]float64 You need to manually create new map. 您需要手动创建新地图。

package main

import (
    "encoding/json"
    "fmt"
)

var exampleResponseData = `{
        "Data":[
            {
                "Type":"pos",
                "Content":{
                    "x":0.5,
                    "y":0.3
                }
            },
            {
                "Type":"vel",
                "Content":{
                    "vx":0.1,
                    "vy":-0.2
                }
            }
        ]
    }`

type response struct {
    Data []struct {
        Type    string
        Content interface{}
    }
}

func main() {
    var response response
    err := json.Unmarshal([]byte(exampleResponseData), &response)
    if err != nil {
        fmt.Println("Cannot process not valid json")
    }

    for i := 0; i < len(response.Data); i++ {
        response.Data[i].Content = convertMap(response.Data[i].Content)
    }
}

func convertMap(originalMap interface{}) map[string]float64 {
    convertedMap := map[string]float64{}
    for key, value := range originalMap.(map[string]interface{}) {
        convertedMap[key] = value.(float64)
    }

    return convertedMap
}

Are you sure you cannot define Content as map[string]float64 ? 您确定无法将Content定义为map[string]float64吗? See example below. 见下面的例子。 If not, how can you know that you can cast it in the first place? 如果没有,你怎么知道你可以把它放在首位?

type response struct {
    Data []struct {
        Type    string
        Content map[string]float64
    }
}

var response response
err := json.Unmarshal([]byte(exampleResponseData), &response)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM