Вырезать из границ, используя [][]int, но работает с картой [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
? Это очень странно.
4 ответа
Когда вы делаете в 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)
}
Смотри в детскую площадку
Давайте упростим ваш код, чтобы сделать его более понятным ( ссылка на игровую площадку):
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 мы узнаем:
Если запрошенный ключ не существует, мы получаем нулевое значение типа значения.
В исходном коде нулевое значение для среза ([]int
), является nil
, а также append()
лечит nil
в качестве первого аргумента в качестве пустого фрагмента.
Но когда мы пытаемся получить доступ к 0-му элементу пустого слайса, мы получаем панику, потому что слайс пуст.
В итоге, append
и второй кусочек вашего типа - красная сельдь в вашем вопросе. Паника возникает при попытке доступа к несуществующему элементу в первом измерении вашего среза.
Код паникует из-за длины фрагмента 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})
Проверьте пример детской площадки
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
дольки. Срезы работают не так, как карты, поэтому индексирование несуществующего элемента вызовет панику.