恐慌:在单个简单地图上分配零地图中的条目

我的印象是,只有当我们想要分配给双映射时,才会发生在 nil 映射错误中的条目分配,也就是说,当试图分配更深级别的映射而更高级别的映射没有时存在,例如:


var mm map[int]map[int]int

mm[1][2] = 3

但它也发生在一个简单的地图上(尽管以 struct 作为键):


package main


import "fmt"


type COO struct {

    x int

    y int

}


var neighbours map[COO][]COO


func main() {

    for i := 0; i < 30; i++ {

        for j := 0; j < 20; j++ {

            var buds []COO

            if i < 29 {

                buds = append(buds, COO{x: i + 1, y: j})

            }

            if i > 0 {

                buds = append(buds, COO{x: i - 1, y: j})

            }

            if j < 19 {

                buds = append(buds, COO{x: i, y: j + 1})

            }

            if j > 0 {

                buds = append(buds, COO{x: i, y: j - 1})

            }

            neighbours[COO{x: i, y: j}] = buds // <--- yields error

        }

    }



    fmt.Println(neighbours)


}

有什么问题?


红糖糍粑
浏览 177回答 2
2回答

qq_遁去的一_1

您需要初始化邻居:&nbsp;var neighbours = make(map[COO][]COO)见第二部分:https ://blog.golang.org/go-maps-in-action每当您尝试将值插入尚未初始化的映射时,您都会感到恐慌。

海绵宝宝撒

在 Golang 中,一切都被初始化为 a zero value,它是未初始化变量的默认值。因此,正如已经设想的那样,地图的零值为零。尝试使用未初始化的地图时,它会出现恐慌。(一种空指针异常)有时它可能很有用,因为如果您知道某物的零值,则不必显式初始化它:var str stringstr += "42"fmt.Println(str)// 42 ; A string zero value is ""var i inti++fmt.Println(i)// 1 ; An int zero value is 0var b boolb = !bfmt.Println(b)// true ; A bool zero value is false如果你有 Java 背景,那也是一样的:原始类型有一个默认值,对象被初始化为 null;现在,对于像chanand这样的更复杂的类型map,零值是nil,这就是你必须使用make实例化它们的原因。指针也有零值。数组和切片的情况有点棘手:var a [2]intfmt.Println(a)// [0 0]var b []intfmt.Println(b)// [] ; initialized to an empty slice编译器知道数组的长度(不能更改)及其类型,因此它已经可以实例化正确数量的内存。所有值都被初始化为零值(与 C 不同,您可以在数组中包含任何内容)。对于切片,初始化为空切片[],可以append正常使用。现在,对于结构,它与数组相同。Go 创建一个结构体,其所有字段都初始化为零值。它进行了深度初始化,示例如下:type Point struct {&nbsp; &nbsp; x int&nbsp; &nbsp; y int}type Line struct {&nbsp; &nbsp; a Point&nbsp; &nbsp; b Point}func main() {&nbsp; &nbsp; var line Line&nbsp; &nbsp; // the %#v format prints Golang's deep representation of a value&nbsp; &nbsp; fmt.Printf("%#v\n", line)}// main.Line{a:main.Point{x:0, y:0}, b:main.Point{x:0, y:0}}最后,interfaceandfunc类型也被初始化为 nil。这就是它的全部。使用复杂类型时,您只需要记住初始化它们。唯一的例外是数组,因为你不能这样做make([2]int)。在您的情况下,您有切片映射,因此您至少需要两个步骤才能在其中放入一些内容:初始化嵌套切片,并初始化第一个映射:var buds []COOneighbours := make(map[COO][]COO)neighbours[COO{}] = buds// alternative (shorter)neighbours := make(map[COO][]COO)// You have to use equal here because the type of neighbours[0] is knownneighbours[COO{}] = make([]COO, 0)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go