📈
generic collection types: java.util.Collections у нас дома 📈
Один из первых вопросов, который задают новички в Go: «где мои привычные коллекции
Set/
Map?». Ответ в виде
map[type1]type2 их обычно не устраивает по трём причинам:
• Нет встроенных методов.
• Нет возможности определения собственного оператора сравнения.
• Нет,
map[comparable]struct{} не является нормальной заменой сетов.
Если первый и последний (особенно последний) это чистая вкусовщина, то вот отсутствие собственных типов в ключах было и остаётся довольно напряжным моментом. Особенно для типов, которые внутри себя содержат указатель, ведь неравны два указателя указывающие на разные участки в памяти, даже если и указывают на семантически одинаковые вещи.
И вот, почти 14 лет от первого релиза языка, и почти 5 лет от релиза дженериков, мы близки к решению этой проблемы. Встречайте:
Уже (почти):•
golang.org/x/exp/collection/hashed.Map: хешмапа поверх
maphash.Hasher.
•
golang.org/x/exp/collection/hashed.Set: хешсет поверх
maphash.Hasher.
•
golang.org/x/exp/collection/set: дженерик сет поверх интерфейса
comparable. По сути есть просто обёртка вокруг
map[T]struct{}, но содержит привычные методы.
•
golang.org/x/exp/collection/sorted.[Map, MapSpan, MapSet, Set]: сортируемые словарь и сет. Используют
cmp.Ordered поэтому свой компаратор пока определить нельзя, но можно все упорядоченные типы (включая объявленные поверх свои).
Ещё на этапе обсуждения:•
golang.org/x/exp/collection/heap: дженерик куча.
•
container/hash: insertion-ordered maps: дженерик словари, итерация по которым, прямо зависит от порядка вставки.
И тут будет логичный вопрос: обобщенные коллекции это конечно круто (хоть и сильно поздно), но где обобщенный интерфейс
как в моей любимой Java? Про общие интерфейсы действительно не забыли, однако в лучших традициях Go Team «лучше не сделать ничего, чем сделать плохо»
их убрали в тестовый файл для проверок, но не для использования. Аргументируют тем, что нет пока понимания какие требования должны быть обязательными к интерфейсам, а какие опциональны.
В любом случае это хорошее изменение, которое позволит многим дропнуть зависимость от очередного самописного модуля коллекций, который в проект затащили ради одного типа
Set.
П.С.
Map не стали завозить ибо уже есть обычный
map[K]V. У которого, впрочем, нет методов, но есть свободные функции.
П.П.С. Кстати вы знали, что можно
связанные списки можно использовать в качестве ключей для map?