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

Ответ

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

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

  • Все простые типы: int, float64, string, bool, complex64, complex128 и т.д.
  • Указатели (*T)
  • Каналы (chan T)
  • Интерфейсы (если их динамические типы сравнимы и имеют одинаковый тип и значение)
  • Структуры и массивы (если все их поля/элементы сравнимы)

Нельзя использовать:

  • Срезы ([]T) – их содержимое может меняться, и они не поддерживают операцию сравнения ==.
  • Функции (func) – они не сравнимы.
  • Map (map[K]V) – они не сравнимы.
  • Структуры или массивы, содержащие несравнимые поля/элементы (например, срез или функцию).

Пример:

m := make(map[[2]int]string) // массив как ключ - ок, так как элементы int сравнимы
m[[2]int{1, 2}] = "value"

type Key struct {
    X int
    Y string
}
m2 := make(map[Key]bool) // структура как ключ - ок, так как поля int и string сравнимы
m2[Key{X: 1, Y: "test"}] = true

// Пример несравнимого типа (срез внутри структуры)
type InvalidKey struct {
    ID int
    Tags []string // Срез, делает InvalidKey несравнимой
}
// var _ map[InvalidKey]int // Ошибка компиляции: InvalidKey is not comparable