Рабочая группа Go Collections, созданная в конце 2025 года, выкатила набор предложений для Go 1.28 — в стандартную библиотеку наконец-то заезжают нормальные коллекции. До сих пор кроме кучи (heap) и встроенных slice с map из коробки почти ничего не было. Множества изображали через map[T]bool или map[T]struct{}, упорядоченные map на деревьях вообще отсутствовали. С появлением generics в Go 1.18 и итераторов в 1.23 появилась возможность сделать библиотечные типы такими же удобными, как встроенные. Группа — Джонатан Амстердам, Алан Донован, Роберт Гриземер, Дэниел Марти, Роджер Пеппе, Кит Рэндалл и Йен Ланс Тейлор — как раз этим и занялась.
Первым делом, ещё в go1.27 через #70471 и CL 657296 заехал hash/maphash.Hasher — стандартный интерфейс для кастомных хэш-функций и сравнения. Он нужен, когда ключи несравнимы (слайсы, map) или сравнение по умолчанию даёт не тот результат, как с types.Type, где требуется глубокое сравнение через types.Identical. На его основе строятся container/hash.Map[K,V] (#69559, CL 612217) и container/hash.Set[T] (#80584, CL 741160) — хэш-таблица и множество с произвольным хэшированием. Для обычных сравнимых элементов предложен container/set.Set[T] (#69230, CL 745441), который прозрачно упаковывает map[T]struct{} и добавляет привычные Union, Intersection и остальные операции. Его продвигают как стандартный тип для новых API. Для старого кода, где сигнатуры не поменять, задуман container/mapset (#77052, CL 724420) — пакет хелперов Union, Intersection над «легаси» map[T]bool и map[T]struct{}.
Упорядоченный map идёт как container/ordered.Map[K,V] (#60630). Текущая реализация на сбалансированном дереве, но интерфейс этого не требует. Полезна, когда нужны range-запросы — простая сортировка ключей map[K]V не всегда тянет. Кучу обновили до container/heap/v2.Heap (#77397) — generic API вместо старого и местами неудобного heap. В перспективе рассматривают insertion-ordered hash maps и стеки.
Чтобы обеспечить единообразие, в пакете container заведены неэкспортируемые интерфейсы _AbstractCollection, _AbstractMap и _AbstractSet. Они используют F-ограниченный полиморфизм (рекурсивные constraint-интерфейсы) для решения «проблемы бинарных методов»: у разных типов метод Union принимает и возвращает именно свой тип, поэтому обычный интерфейс не подходит. Эти абстракции нужны для тестов и обобщённых хелперов, экспортировать их пока не собираются. Как пример — функция Take, умеющая вытащить произвольный элемент из любого подходящего множества.
В дизайне намеренно оставили максимум полезной отдачи от методов: мутации сообщают, изменился ли размер, Map.Set и Delete возвращают предыдущее значение и признак наличия. Операции над множествами вроде Union и Intersection входят в интерфейс Set ради эффективных специализированных реализаций, хотя многие из них можно было бы выразить абстрактно через All, Len и Contains. Вторичные операции вроде Subset убрали из интерфейса и сделали generic-функциями. DeleteFunc сохранили, потому что для дерева условное удаление без неё оборачивается O(n log n) вместо линейного. Все алгебраические операции имеют две формы: возвращающую новое множество и -With-вариант, который мутирует левый операнд. Сливать их в один метод не стали — учли опыт math/big.Int и риск случайных мутаций. Для симметрии методы AbstractMap почти копируют существующий пакет maps, а для пробелов вроде maps.Contains обсуждается отдельный proposal.