Ответ
Ключевое различие в том, как nil-значения map и slice ведут себя при операциях записи.
Хотя zero value для обоих типов — это nil, их поведение кардинально отличается.
Zero Value для map
- Значение:
nil. - Поведение: Попытка записи в
nil-map вызовет панику (panic: assignment to a nil map). Чтение, вызовlenилиrangeдляnil-map безопасны и не вызовут панику (вернут zero value для типа значения и 0 соответственно). - Инициализация: Перед использованием
mapдля записи её необходимо явно инициализировать с помощьюmake()или литерала.
var m map[string]int // m is nil
fmt.Println(m["key"]) // Безопасно, вернет 0
fmt.Println(len(m)) // Безопасно, вернет 0
m["key"] = 1 // !!! panic: assignment to a nil map
// Правильная инициализация
m = make(map[string]int)
m["key"] = 1 // OKZero Value для slice
- Значение:
nil. - Поведение:
nil-слайс можно безопасно использовать со встроенной функциейappend. При первом вызовеappendдляnil-слайса Go автоматически выделит память под новый нижележащий массив. Однако обращение к элементу по индексу вызовет панику. - Инициализация: Явная инициализация перед
appendне требуется.
var s []int // s is nil, len(s) == 0, cap(s) == 0
// Безопасно: Go выделит память и добавит элемент
s = append(s, 42)
fmt.Println(s) // Выведет [42]
fmt.Println(len(s)) // Выведет 1
// А вот так делать нельзя
var s2 []int // s2 is nil
s2[0] = 100 // !!! panic: runtime error: index out of rangeСравнительная таблица
| Операция | var m map[T]T (nil map) | var s []T (nil slice) |
|---|---|---|
Чтение (v := m[k]) | ✅ Безопасно | ❌ Паника (по индексу) |
len() | ✅ Безопасно (возвращает 0) | ✅ Безопасно (возвращает 0) |
Запись (m[k] = v) | ❌ Паника | ❌ Паника (по индексу) |
append() | (неприменимо) | ✅ Безопасно |