Ответ
Ключевое различие: массив (array
) — можно использовать как ключ, а срез (slice
) — нельзя.
Почему так?
Ключом в map
в Go может быть любой тип данных, который является сравнимым (comparable), то есть для которого определена операция сравнения ==
.
-
Массивы (
array
) являются сравнимыми, если их элементы тоже сравнимы. Сравнение двух массивов происходит поэлементно. Поэтому их можно использовать в качестве ключей.// РАБОТАЕТ m := make(map[[2]int]string) key := [2]int{10, 20} m[key] = "value" fmt.Println(m[[2]int{10, 20}]) // Выведет: value
-
Срезы (
slice
), с другой стороны, по спецификации языка не являются сравнимыми (их можно сравнивать только сnil
). Срез — это, по сути, легковесная структура, содержащая указатель на нижележащий массив, длину и ёмкость. Сравнение указателей не дало бы желаемого результата (сравнения содержимого), поэтому эту операцию для срезов запретили, чтобы избежать ошибок. Как следствие, срезы не могут быть ключами вmap
.// ОШИБКА КОМПИЛЯЦИИ // m := make(map[[]int]string) // Получим ошибку: invalid map key type []int
Что делать, если нужно использовать срез как ключ?
Самый правильный подход — пересмотреть архитектуру. Если это абсолютно необходимо, можно преобразовать срез в строку, которая является сравнимым типом:
// Преобразование в строку - частый паттерн для []byte
byteSliceKey := []byte("mykey")
stringKey := string(byteSliceKey)
m := make(map[string]string)
m[stringKey] = "data"