Ответ
Рост мапы в Go происходит, когда она становится слишком заполненной. Этот процесс называется rehashing (или эвакуация) и заключается в увеличении количества бакетов (buckets) в два раза.
Триггеры для rehashing:
- Коэффициент загрузки (Load Factor): Среднее количество элементов на один бакет превышает
6.5
. - Переполнение: Слишком много бакетов используют свои "дополнительные" бакеты (overflow buckets).
Как происходит процесс:
- Создание нового хранилища: Go runtime выделяет новый массив бакетов, в два раза большего размера.
- Инкрементальное копирование: Перенос данных из старых бакетов в новые происходит не сразу, а постепенно (амортизированно), чтобы избежать длительных пауз в работе приложения.
- При каждой операции записи или удаления из мапы, Go переносит данные из одного или двух старых бакетов в новые.
- При чтении из мапы, если ключ находится в бакете, который еще не перенесен, поиск происходит и в старом, и в новом месте.
- Завершение: Когда все данные скопированы, старый массив бакетов освобождается сборщиком мусора.
Важная особенность:
- Сама по себе мапа в Go не является потокобезопасной. Для конкурентного доступа к мапе из нескольких горутин необходимо использовать внешнюю синхронизацию, например,
sync.RWMutex
или использоватьsync.Map
.