12 вопросов
Map в Go - встроенная хеш-таблица для хранения пар ключ-значение. Ключевые особенности: отсутствие гарантированного порядка, panic при записи в nil map, ограничения на типы ключей.
Встроенная функция len() работает с map, строками, слайсами, массивами и каналами. У map нет методов .length() или .size() - Go предпочитает встроенные функции методам.
Подробнее →Идиома "comma ok": если ключ существует, ok = true, v - значение. Если нет, ok = false, v - zero value. В Go нет оператора in (как в Python) или метода .has().
Подробнее →Встроенная функция delete(m, key) удаляет элемент. Безопасно вызывать для несуществующего ключа или nil map - просто ничего не произойдёт. Не возвращает значений.
Подробнее →Go намеренно рандомизирует порядок итерации map, чтобы программисты не зависели от конкретного порядка. Каждый запуск range по map может дать разный порядок. Для упорядоченного перебора: извлеките ключи в слайс, отсортируйте, переберите.
Подробнее →Чтение из nil map безопасно (вернёт zero value), но запись вызывает panic: assignment to entry in nil map. Перед записью map нужно инициализировать: m := make(map[string]int) или m := map[string]int{}.
Подробнее →var m map[string]int; fmt.Println(m["key"])? 🟡 Средний
▶
Чтение из nil map не вызывает panic - возвращается zero value типа значения. Для int это 0. Это поведение одинаково для nil map и для отсутствующего ключа в инициализированной map.
Подробнее →Go намеренно рандомизирует порядок итерации по map, чтобы программисты не полагались на него. Если нужен порядок - отсортируйте ключи отдельно или используйте слайс пар.
Подробнее →Ключи map должны быть сравнимыми (поддерживать ==). Слайсы несравнимы, поэтому не могут быть ключами. Массивы - могут ([3]int сравним). Структуры - только если все поля сравнимы.
Подробнее →m := map[string]struct{X int}{"a": {1}}; m["a"].X = 2? 🟡 Средний
▶
Значения в map не адресуемы - нельзя получить указатель на элемент map, потому что map может перемещать данные при росте. m["a"].X = 2 не скомпилируется. Решение: извлечь значение в переменную, изменить, записать обратно. Или использовать map[string]*struct{X int}.
Подробнее →map[string]*User лучше map[string]User для модификации значений? 🟡 Средний
▶
В map[string]User нельзя модифицировать поля напрямую (m[k].Name = "x" не скомпилируется). С map[string]*User можно: m[k].Name = "x" меняет объект по указателю. Компромисс: указатели создают нагрузку на GC, но позволяют менять значения без копирования.
Подробнее →dst := src копирует только указатель - оба map'а ссылаются на одни данные. copy() не работает с map. Правильно: maps.Clone(src) из Go 1.21 или цикл for k, v := range src { dst[k] = v }. Для вложенных map/slice нужна глубокая копия.
Подробнее →for range? 🔴 Сложный
▶
Спецификация Go явно разрешает удаление ключей из map во время итерации range. Удалённый ключ не будет посещён, если до него ещё не дошли. Новые ключи, добавленные при итерации, могут быть посещены, а могут и нет.
Подробнее →