Golang 中的嵌套映射

新手上路,请多包涵
func main() {
    var data = map[string]string{}
    data["a"] = "x"
    data["b"] = "x"
    data["c"] = "x"
    fmt.Println(data)
}

它运行。

 func main() {
    var data = map[string][]string{}
    data["a"] = append(data["a"], "x")
    data["b"] = append(data["b"], "x")
    data["c"] = append(data["c"], "x")
    fmt.Println(data)
}

它也运行。

 func main() {
    var w = map[string]string{}
    var data = map[string]map[string]string{}
    w["w"] = "x"
    data["a"] = w
    data["b"] = w
    data["c"] = w
    fmt.Println(data)
}

它再次运行!

 func main() {
    var data = map[string]map[string]string{}
    data["a"]["w"] = "x"
    data["b"]["w"] = "x"
    data["c"]["w"] = "x"
    fmt.Println(data)
}

但是它失败了!?

Go 中的嵌套地图有问题吗?还是嵌套地图不支持多括号?

原文由 Özgür Yalçın 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 691
2 个回答

地图类型的 零值为 nil 。它尚未初始化。您不能将值存储在 nil 映射中,这是运行时恐慌。

在上一个示例中,您初始化了(外部) data 映射,但它没有条目。当您像 data["a"] 一样对其进行索引时,由于其中没有包含 "a" 键的条目,因此对其进行索引会返回值类型的零值,即 nil 对于地图。因此,尝试分配给 data["a"]["w"] 是运行时恐慌。

在将元素存储到其中之前,您必须先初始化地图,例如:

 var data = map[string]map[string]string{}

data["a"] = map[string]string{}
data["b"] = make(map[string]string)
data["c"] = make(map[string]string)

data["a"]["w"] = "x"
data["b"]["w"] = "x"
data["c"]["w"] = "x"
fmt.Println(data)

输出(在 Go Playground 上尝试):

 map[a:map[w:x] b:map[w:x] c:map[w:x]]

请注意,当您声明地图类型的变量并使用 复合文字 对其进行初始化时(如 var data = map[string]string{} ),这也算作初始化。

请注意,您还可以使用复合文字初始化嵌套映射:

 var data = map[string]map[string]string{
    "a": map[string]string{},
    "b": map[string]string{},
    "c": map[string]string{},
}

data["a"]["w"] = "x"
data["b"]["w"] = "x"
data["c"]["w"] = "x"
fmt.Println(data)

输出是一样的。在 Go Playground 上尝试一下。

原文由 icza 发布,翻译遵循 CC BY-SA 3.0 许可协议

虽然这个问题最直接的答案是如前所述初始化您的嵌套映射,但根据您的访问模式,还有另一个可能的选择。如果您需要一个真正的地图分层系统,那么前面的答案就可以了。但是,如果您只需要使用多个方面在地图中查找值,请继续阅读!

映射使用 结构 作为键是完全可以接受的(事实上,任何可 比较 的都可以使用)。因此,您可以使用带有结构键的单个映射, 例如来自 Golang 博客的示例,这是一个按国家/地区跟踪页面点击率的点击计数器:

 type Key struct {
  Path, Country string
}

hits := make(map[Key]int)

// set: Vietnamese person visiting the home page
hits[Key{"/", "vn"}]++

// get: see how many Chinese persons read the spec
n := hits[Key{"/ref/spec", "cn"}]

我很少看到这样的地图,相反,许多人首先使用嵌套变体,我认为这可能并不总是合适的。

原文由 Dominic Barnes 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题