Ответ
Ключом в 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)