首页 >后端开发 >Golang >为什么 Go 中的嵌套映射在直接访问时会导致运行时恐慌,而在使用追加或初始化时却不会?

为什么 Go 中的嵌套映射在直接访问时会导致运行时恐慌,而在使用追加或初始化时却不会?

Mary-Kate Olsen
Mary-Kate Olsen原创
2024-12-04 06:17:11821浏览

Why Do Nested Maps in Go Cause Runtime Panics When Accessed Directly, But Not When Using Append or Initialization?

Golang 中的嵌套映射:探索异常

探索 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)
}

有问题。

排查原因

导致这个问题的原因是map类型的零值为nil。零值未初始化。你不能在 nil 映射中存储值。这是运行时恐慌。

在上一个示例中,我们初始化了(外部)数据映射,但没有条目。如果您像 data["a"] 这样建立索引,则还没有“a”键的条目,因此索引返回值类型为 nil 的零值。因此,如果您尝试分配给数据“a”,则会发生运行时恐慌。

在存储任何元素之前必须初始化地图。例如:

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]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 游乐场尝试一下。

以上是为什么 Go 中的嵌套映射在直接访问时会导致运行时恐慌,而在使用追加或初始化时却不会?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn