На этом шаге рассмотрим понятие "отображения " в Go.
Отображения в языке Go – это неупорядоченные коллекции пар ключ/значение, емкость которых ограничивается лишь объемом доступной памяти. Ключи имеют уникальные значения в пределах коллекции и могут быть только одного типа, поддерживающего операторы == и != , то есть в качестве ключей могут использоваться значения большинства встроенных типов (таких как int, float64, rune, string, сравнимые массивы и структуры, а также пользовательские типы, основанные на них, и указатели). Срезы, несравнимые массивы и структуры (элементов и полей которых не поддерживают операторы == и !=), а также пользовательские типы, основанные на них, не могут играть роль ключей в отображениях. В качестве значений могут использоваться указатели, значения ссылочных типов, а также значения встроенных или пользовательских типов, включая отображения, что позволяет легко создавать структуры данных произвольной сложности.
Отображения – это ссылочный тип. 8 байт на 64-битных архитектурах и 4 байта – на 32-битных), независимо от объема данных, хранимых в отображениях. Поиск по отображениям выполняется очень быстро – намного быстрее линейного поиска, но примерно на два порядка (то есть в 100 раз) медленнее операции доступа к элементам массивов и срезов по их индексам. Тем не менее скорость поиска достаточно высока, чтобы можно было использовать отображения, где это имеет смысл.
На рис. 1 схематически представлено строение отображения типа map[string]float64.
Рис.1. Устройство отображения с ключами – строками и значениями типа float64
Поскольку срезы не могут играть роль ключей, может показаться, что в качестве ключей нельзя также использовать и срезы с байтами ([]byte). Однако, поскольку преобразования string([]byte) и []byte(string) не изменяют байты данных, можно спокойно преобразовывать значения типа []byte в тип string, использовать их как ключи отображения и преобразовывать обратно в значения типа []byte при необходимости.
Все ключи отображения должны быть одного типа, то же относится и к значениям, хотя значения и ключи могут быть разных типов (как часто и бывает). Однако что касается значений в отображениях, на них, как и на элементы среза, практически не накладывается серьезных ограничений, потому что типом значения может быть интерфейс. То есть в отображении можно хранить значения любых типов, при условии что все они будут соответствовать указанному интерфейсу (иметь метод или методы, объявленные интерфейсом).
Можно даже создать отображение со значениями, имеющими тип пустого интерфейса, interface{}, и хранить в нем значения любых типов, однако при обращении к ним придется использовать инструкции приведения типа, выбора по типу или механизм интроспекции, чтобы обеспечить корректное их использование.
На следующем шаге рассмотрим операции, поддерживаемые отображениями в Go.