Какие требования предъявляются к типам данных, используемым в качестве ключей в `map` в Go?

Ответ

Ключом в map в Go может быть любой тип данных, для которого определена операция сравнения на равенство (==) и неравенство (!=). Такие типы в спецификации языка называются сравниваемыми (comparable).

Это требование необходимо, потому что map — это хеш-таблица. Для работы ей нужно уметь:

  1. Вычислять хеш от ключа, чтобы определить его местоположение (бакет).
  2. Сравнивать ключи на равенство для разрешения коллизий (когда у разных ключей одинаковый хеш).

Какие типы можно использовать в качестве ключа:

  • Все числовые типы (int, float64 и т.д.)
  • Строки (string)
  • Булевы значения (bool)
  • Указатели (*T)
  • Каналы (chan T)
  • Интерфейсы (только если динамический тип, хранящийся в интерфейсе, является сравниваемым)
  • Структуры (struct), если все их поля являются сравниваемыми типами.
  • Массивы ([N]T), если их элементы (T) являются сравниваемыми типами.

Какие типы использовать НЕЛЬЗЯ:

Эти типы не поддерживают операцию сравнения ==.

  • Слайсы ([]T)
  • Карты (map[K]V)
  • Функции (func())

Пример:

// Корректные ключи
m1 := make(map[string]int)      // Строка
m2 := make(map[int]bool)         // Целое число
type Point struct{ X, Y int }
m3 := make(map[Point]string)     // Структура со сравниваемыми полями

// Некорректные ключи
// m4 := make(map[[]int]string)  // Ошибка компиляции: invalid map key type []int
// m5 := make(map[map[string]int]bool) // Ошибка компиляции: invalid map key type map[string]int

Частый кейс: Если нужно использовать слайс байт ([]byte) в качестве ключа, его можно преобразовать в строку: string(myByteSlice).