Есть ли параметры у мапы в Go, например возможность заранее задать размер
Что проверяют
Знаете ли вы, что make для мапы принимает подсказку размера, и чем она отличается от ёмкости среза. Следом обычно спрашивают, освобождается ли память после удаления ключей и почему мапа не потокобезопасна.
Как отвечать
Параметр у мапы ровно один: подсказка начального размера.
- хинт:
m := make(map[string]int, 1000)заранее выделяет место примерно под 1000 элементов, чтобы при заполнении не было роста с переносом записей.len(m)после этого равен 0, аcap(m)для мапы не компилируется: ёмкости как свойства у неё нет; - когда полезно: итоговый размер известен заранее, например индекс из среза
make(map[int]User, len(users)). Эффект проверяют бенчмарком сb.ReportAllocs(): падает число аллокаций при вставке. На скорость чтения хинт не влияет; - чего нет: своей хеш-функции, коэффициента заполнения, порядка обхода. Ключ обязан быть сравнимым типом, порядок итерации намеренно случайный;
- устройство: с Go 1.24 мапа реализована как Swiss Table, до этого были бакеты по 8 элементов. Смысл хинта от этого не поменялся.
Про память скажите отдельно: мапа не сжимается. После delete большинства ключей или после clear(m) из Go 1.21 выделенная память остаётся за мапой. Чтобы её вернуть, создают новую мапу и копируют живые элементы, старую заберёт сборщик мусора.
И про конкурентность: одновременная запись из нескольких горутин даёт fatal error: concurrent map writes, которую recover не перехватывает. Нужен sync.RWMutex или, для узких сценариев вроде кеша с редкой записью, sync.Map.
Где спотыкаются
Путают хинт с ограничением и думают, что мапа из make(map[K]V, 10) не вырастет больше десяти элементов. Растёт без ограничений.
Задают хинт «с запасом» в миллион на всякий случай. Память выделяется сразу и не возвращается, пока мапа жива.
Ждут, что после удаления ключей мапа станет меньше, и удивляются памяти процесса с долгоживущим кешем.