Ответ
Ключом в map
в Go может быть любой тип данных, для которого определена операция сравнения на равенство (==
и !=
). Такие типы называются сравниваемыми (comparable).
Почему именно это требование?
Хеш-таблица (которой является map
) должна уметь делать две вещи:
- Вычислять хеш от ключа, чтобы определить, в какой "корзине" (bucket) хранить значение.
- Сравнивать ключи внутри одной корзины, чтобы найти точное совпадение (на случай коллизий хешей).
В Go требование сравниваемости гарантирует, что для типа можно выполнить обе эти операции.
Разрешенные типы (сравниваемые):
- Числовые типы:
int
,float64
,complex128
и т.д. - Строки:
string
. - Булевы значения:
bool
. - Указатели:
*T
(сравниваются адреса, на которые они указывают). - Каналы:
chan T
(сравниваются указатели на внутреннюю структуру канала). - Интерфейсы:
interface{}
(сравниваются, если их динамические типы и значения сравнимы). - Структуры:
struct
, если все их поля являются сравниваемыми типами. - Массивы:
[N]T
, если тип элементовT
является сравниваемым.
Запрещенные типы (несравниваемые):
- Срезы (
[]T
): Нельзя, так как содержимое среза может измениться, даже если сам заголовок среза (указатель, длина, емкость) останется прежним. Сравнение указателей было бы бессмысленным. - Карты (
map[K]V
): Нельзя, так как они сами по себе не поддерживают операцию сравнения. - Функции (
func()
): Нельзя, так как для них не определена операция сравнения.
Пример:
// Корректные ключи
type MyStruct struct {
ID int
Name string
}
m := make(map[MyStruct]bool)
m[MyStruct{1, "test"}] = true
// Некорректный ключ - вызовет ошибку компиляции
// type BadStruct struct {
// Data []int // Срез - несравниваемый тип
// }
// invalidMap := make(map[BadStruct]string)