Что такое хеш-коллизия и как с ней работают в Go?

Ответ

Хеш-коллизия — это ситуация, когда хеш-функция генерирует одинаковый хеш-код для двух или более разных ключей. Это неизбежное явление, поскольку количество возможных ключей часто бесконечно, а количество возможных хеш-кодов ограничено размером хеш-таблицы.

Как Go обрабатывает коллизии в map?

Go использует метод цепочек (chaining). Каждый элемент массива (бакет) в реализации map является указателем на связанный список (или похожую структуру) пар ключ-значение.

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

Последствия коллизий:

  • Снижение производительности: Вместо мгновенного доступа по индексу (O(1)), системе приходится перебирать элементы в цепочке, что в худшем случае приводит к сложности O(n). Для защиты от этого Go использует качественные хеш-функции и механизм перебалансировки таблицы при её заполнении.
  • Атаки на отказ в обслуживании (Hash-DoS): Злоумышленник может намеренно подобрать ключи, которые вызывают максимальное количество коллизий, чтобы замедлить работу системы. В современных версиях Go в хеш-функцию для строк добавляется случайное "зерно" (seed) при старте программы, что делает такие атаки труднореализуемыми.