Что можно делать с nil мапой в Go
Что проверяют
Знаете ли вы нулевые значения типов в Go и разницу между nil мапой и пустой. Ответ показывает, читали ли вы спецификацию или выучили правило «мапу надо сделать через make» без понимания, что именно ломается.
Как отвечать
Объявление var m map[string]int даёт nil мапу. Читать из неё безопасно:
m["a"]вернёт нулевое значение типа, дляintэто 0;v, ok := m["a"]дастokравным false;len(m)вернёт 0;rangeне сделает ни одной итерации;delete(m, "a")ничего не делает и не паникует;- сравнение
m == nilразрешено.
Паникует ровно одна операция, запись: m["a"] = 1 даёт assignment to entry in nil map. Поэтому nil мапа вполне годится как пустая мапа только для чтения, и функция, которая принимает map и лишь читает, работает без проверок. Инициализация: make(map[string]int) или литерал map[string]int{}.
Стоит добавить две вещи рядом. Мапы нельзя сравнивать между собой, только с nil, содержимое сверяют через maps.Equal. И мапа не потокобезопасна: одновременные чтение и запись роняют весь процесс сообщением concurrent map writes, спасает мьютекс или sync.Map.
Где спотыкаются
Считают, что чтение из nil мапы паникует, и обвешивают код лишними проверками. Паника только на записи, и знание этого экономит половину защитного кода.
Забывают про мапу внутри структуры. Нулевое значение структуры содержит nil мапу, и первая же запись в поле падает. Лечится конструктором или ленивой инициализацией перед первой записью.
Переносят на мапу правило слайса. В nil слайс можно добавлять через append, который сам выделит массив, у мапы такого механизма нет, отсюда ложный вывод, что нулевое значение в Go всегда готово к записи. Вторая половина той же ошибки: создать мапу внутри функции, которая приняла её параметром, и удивиться, что снаружи всё ещё nil.