1

为什么这段代码有效

graph := make(map[int][]int, 0)

graph[0] = append(graph[0], 1)

但是如果你用graph := make([][]int, 0)I get替换第一行panic: runtime error: index out of range?这很奇怪。

4

4 回答 4

6

让我们简化您的代码,以使正在发生的事情更加明显(游乐场链接):

graph1 := make(map[int]int, 0)
graph2 := make([]int, 0)

x := graph1[0] // Success
y := graph2[0] // Panic

从这里我们看到差异是由于map[int]vs []int- 您类型中的第二个数组实际上是无关紧要的。

现在要了解为什么会发生这种情况,我们需要了解 Go 如何处理 map 和 slice 访问。从Go Maps in Action 中,我们了解到:

如果请求的键不存在,我们会得到值类型的零值

[]int在您的原始代码中,切片 ( )的零值是nil,并将第一个参数append()视为nil空切片。

但是当我们尝试访问空切片的第 0个元素时,我们会感到恐慌,因为切片是空的。

总之,append您的类型的第二部分在您的问题中都是红鲱鱼。尝试访问切片第一维中不存在的元素时会发生恐慌。

于 2018-05-19T16:56:34.750 回答
2

当你做 make in 时graph := make(map[int][]int, 0),你正在为你的地图分配内存,而不是数组。所以你可能只这样做 graph := make(map[int][]int)

分解你的代码:

type a []int
type m map[int]a

func main() {
    fmt.Println("Hello, playground")

    //decomping graph := make(map[int][]int, 0)
    graph := make(m)

    //map is empty
    fmt.Println(len(graph))

    //decomping graph[0] := append(graph[0], 1)
    itm_a := 1
    arr_a := []int{}

    //appeding item to "a" type
    arr_a = append(arr_a, itm_a)

    //appending array of a to graph
    graph[0] = arr_a

    //print graph
    fmt.Println(graph)
}

操场上见。

您得到的错误是由概念错误引起的。当你这样做时graph := make([][]int, 0),你将内存分配给一个切片,而不是一个数组。请参阅https://blog.golang.org/go-slices-usage-and-internals

所以你可以这样做(反解解决方案):

type a []int
type m []a

func main() {
    fmt.Println("Hello, playground")

    //decomping graph := make([][]int, 0)
    //see that you must be set the length
    graph := make(m, 0)

    //map is empty
    fmt.Println(len(graph))

    //this is incorrect: graph[0] := append(graph[0], 1)
    //this is correct:   graph[0] := append(graph[0], []int{1})
    //see:
    itm_a := 1
    arr_a := []int{}

    //appeding item to "a" type
    arr_a = append(arr_a, itm_a)

    //appending slice of a to graph (slice)
    graph = append(graph, arr_a)

    //print graph
    fmt.Println(graph)
}

操场上看

于 2018-05-19T17:14:38.520 回答
2

由于切片长度为0. 如果您想将任何内容附加到切片,您只需提供其长度,如下所示。

graph := make([][]int, 1)
fmt.Println(len(graph))
graph[0] = append(graph[0], 1)
fmt.Println(graph)

要将数据附加到第一级的切片,请附加到其第一个索引,然后附加到第二级,如下所示。

graph := make([][]int, 0)
fmt.Println(len(graph))
graph = append(graph, []int{1})

检查游乐场示例

于 2018-05-19T16:46:24.073 回答
1

make(map[int][]int, 0)创建一个map.[]int

通过 Go 中的设计,您可以从地图中获取任何元素。如果它不存在,您会收到“零”值,这里是一个空切片。

graph := make(map[int][]int)

graph[4] = append(graph[4], 1)
graph[7] = append([]int{}, 1, 2)
graph[11] = append([]int{1, 2, 3}, 4, 5)

打印它给出了这个切片:

fmt.Printf("%#v\n", graph)

map[int][]int{
    4:[]int{1},
    7:[]int{1, 2},
    11:[]int{1, 2, 3, 4, 5},
}

您的第二个示例创建了一个空[]int切片。切片与地图的工作方式不同,因此索引不存在的元素会让您感到恐慌。

于 2018-05-19T17:00:58.507 回答