使用 [][]int 切片超出范围但适用于 map[int][]int
Slice out of bounds using [][]int but works with map[int][]int
为什么这段代码有效
graph := make(map[int][]int, 0)
graph[0] = append(graph[0], 1)
但是如果你用 graph := make([][]int, 0)
替换第一行,我会得到 panic: runtime error: index out of range
?很奇怪。
由于切片长度为 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})
让我们简化您的代码,使发生的事情更加明显 (Playground link):
graph1 := make(map[int]int, 0)
graph2 := make([]int, 0)
x := graph1[0] // Success
y := graph2[0] // Panic
从这里我们看到差异是由于 map[int]
与 []int
- 您的类型中的第二个数组实际上是无关紧要的。
现在要了解为什么会发生这种情况,我们需要了解 Go 如何处理映射和切片访问。从 Go Maps in Action 我们了解到:
If the requested key doesn't exist, we get the value type's zero value.
在您的原始代码中,切片 ([]int
) 的零值是 nil
,并且 append()
将 nil
作为第一个参数视为空切片。
但是当我们尝试访问空切片的第 0th 元素时,我们会出现恐慌,因为切片是空的。
总而言之,append
和您的类型的第二部分在您的问题中都是转移注意力的问题。尝试访问切片的第一维中不存在的元素时会发生恐慌。
make(map[int][]int, 0)
创建 map
的 []int
。
根据 Go 的设计,您可以从地图中获取任何元素。如果它不存在,您会收到 "zero" 值,这是一个空切片。
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
个切片的空切片。切片与地图的工作方式不同,因此索引一个不存在的元素会让您感到恐慌。
当您在 graph := make(map[int][]int, 0)
中进行 make 时,您是在将内存分配给映射,而不是数组。所以你只能这样做
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)
}
参见playground。
您遇到的错误是由概念错误引起的。
当您执行 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)
}
为什么这段代码有效
graph := make(map[int][]int, 0)
graph[0] = append(graph[0], 1)
但是如果你用 graph := make([][]int, 0)
替换第一行,我会得到 panic: runtime error: index out of range
?很奇怪。
由于切片长度为 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})
让我们简化您的代码,使发生的事情更加明显 (Playground link):
graph1 := make(map[int]int, 0)
graph2 := make([]int, 0)
x := graph1[0] // Success
y := graph2[0] // Panic
从这里我们看到差异是由于 map[int]
与 []int
- 您的类型中的第二个数组实际上是无关紧要的。
现在要了解为什么会发生这种情况,我们需要了解 Go 如何处理映射和切片访问。从 Go Maps in Action 我们了解到:
If the requested key doesn't exist, we get the value type's zero value.
在您的原始代码中,切片 ([]int
) 的零值是 nil
,并且 append()
将 nil
作为第一个参数视为空切片。
但是当我们尝试访问空切片的第 0th 元素时,我们会出现恐慌,因为切片是空的。
总而言之,append
和您的类型的第二部分在您的问题中都是转移注意力的问题。尝试访问切片的第一维中不存在的元素时会发生恐慌。
make(map[int][]int, 0)
创建 map
的 []int
。
根据 Go 的设计,您可以从地图中获取任何元素。如果它不存在,您会收到 "zero" 值,这是一个空切片。
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
个切片的空切片。切片与地图的工作方式不同,因此索引一个不存在的元素会让您感到恐慌。
当您在 graph := make(map[int][]int, 0)
中进行 make 时,您是在将内存分配给映射,而不是数组。所以你只能这样做
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)
}
参见playground。
您遇到的错误是由概念错误引起的。
当您执行 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)
}