Как Go-мапа (map) растет и когда это происходит? Опишите процесс rehashing.

Ответ

Рост мапы в Go происходит, когда она становится слишком заполненной. Этот процесс называется rehashing (или эвакуация) и заключается в увеличении количества бакетов (buckets) в два раза.

Триггеры для rehashing:

  1. Коэффициент загрузки (Load Factor): Среднее количество элементов на один бакет превышает 6.5.
  2. Переполнение: Слишком много бакетов используют свои "дополнительные" бакеты (overflow buckets).

Как происходит процесс:

  1. Создание нового хранилища: Go runtime выделяет новый массив бакетов, в два раза большего размера.
  2. Инкрементальное копирование: Перенос данных из старых бакетов в новые происходит не сразу, а постепенно (амортизированно), чтобы избежать длительных пауз в работе приложения.
    • При каждой операции записи или удаления из мапы, Go переносит данные из одного или двух старых бакетов в новые.
    • При чтении из мапы, если ключ находится в бакете, который еще не перенесен, поиск происходит и в старом, и в новом месте.
  3. Завершение: Когда все данные скопированы, старый массив бакетов освобождается сборщиком мусора.

Важная особенность:

  • Сама по себе мапа в Go не является потокобезопасной. Для конкурентного доступа к мапе из нескольких горутин необходимо использовать внешнюю синхронизацию, например, sync.RWMutex или использовать sync.Map.