Go Finally Commits to Standard Library Collections
A working group of Go's most senior engineers targets generic sets, ordered maps, and a sane heap for Go 1.28.
Four years after generics shipped, the Go team has finally said the quiet part out loud: the standard library is getting real collection types. An umbrella proposal filed this week by Alan Donovan — golang/go#80590 — lays out the roadmap from the Go Collections working group, a late-2025 assembly of some of the most senior names in the project: Donovan, Jonathan Amsterdam, Robert Griesemer, Daniel Martí, Roger Peppe, Keith Randall, and Ian Lance Taylor. The target is Go 1.28, which puts generic sets, ordered maps, and a usable heap in the standard library around February 2027.
That's a long runway, but the direction is now unambiguous. If you maintain a third-party set library, start writing your deprecation notice.
Why it took this long
Go 1.18 landed generics in March 2022, and the obvious question — "so where's set.Set?" — has been open ever since. A community proposal for a generic set type has been sitting in the issue tracker since September 2024, and discussions go back to 2021. The official answer was always some variant of "wait": first for experience with generics in golang.org/x/exp, then for iterators.
That second wait turned out to be the load-bearing one. Go 1.23's range-over-func iterators (August 2024) gave library-defined types something they never had before: a way to participate in for range like built-in maps and slices do. The proposal is explicit that this is what changed the calculus — with iter.Seq[E] and iter.Seq2[K,V], a stdlib Set can feel native rather than bolted on. Anyone who used container/list in anger knows what bolted-on feels like.
The last prerequisite ships next month. Go 1.27, due in August 2026, adds maphash.Hasher[T] — a small interface pairing a Hash method with an Equal method, plus a ComparableHasher default for types where == does the right thing. It's the contract every future hash-based structure in the stdlib will build on.
What's actually in the box
The Go 1.28 slate, per the umbrella issue:
container/set.Set[E]— the canonical set for comparable types, and the piece with the cleverest design decision: it's transparently defined in terms ofmap[E]struct{}. You can assign betweenset.Set[string]and a plainmap[string]struct{}, calllen()on it, range over it, even do_, ok := s[elem]. Every codebase carrying hand-rolledmap[string]struct{}boilerplate gets a migration path that's assignment-compatible, not rewrite-the-world.container/hash.Map[K,V]andhash.Set[E]— hash tables that take a custommaphash.Hasher, for keys that aren't comparable (slices, say) or where==is wrong. The motivating example isgo/types, where twotypes.Typevalues needtypes.Identicalsemantics, not pointer equality. Case-insensitive string keys are the everyday version of the same problem.container/ordered.Map[K,V]— a sorted map backed by a binary tree.container/heap/v2.Heap— a generic replacement for the currentcontainer/heap, whose implement-five-methods-including-sort.InterfaceAPI has been a rite of passage nobody enjoys. This alone will delete a lot of ceremonialPush/Popcode from priority-queue implementations.container/mapset— helper functions for code staying on raw map-based sets.
Insertion-ordered maps and stacks are named as likely follow-ups. Amusingly, the working group says it prefers the term "collection" over "container" to avoid Linux-container confusion — but the packages live in container/ anyway, because that tree already exists.
The restraint is the feature
Two design calls stand out as very Go. First, mutation methods report what happened: Set and Delete return the previous value and a boolean, so you can distinguish "was absent" from "was the zero value" without a second lookup. Second, set operations come in both functional flavors (Union returns a fresh set) and allocation-conscious mutating variants (UnionWith modifies the receiver) — a concession to the reality that convenience APIs get banned from hot paths.
The most consequential decision, though, is a deferral. The group sketched abstract constraint interfaces — the machinery that would let you write one generic function over any set implementation — and then declined to export them until there's real-world experience. That's the lesson of a decade of premature abstraction in other languages' collection hierarchies, applied preemptively. Java's Collection interface is 28 years of accumulated regret; Go is opting to ship concrete types first and unify later, if ever.
The group is also explicit that it's prioritizing correctness and simplicity over constant-factor performance. Read that as a survival notice for the ecosystem's specialized structures: if you're on google/btree or a Swiss-table variant for throughput reasons, the stdlib's ordered.Map probably won't dethrone it. What dies is the long tail of general-purpose set libraries — deckarep/golang-set and its many cousins — whose entire reason to exist was a gap that's now closing.
What to do with this now
Nothing ships tomorrow, and that's fine. The practical sequence: when Go 1.27 lands in August, look at maphash.Hasher if you maintain any custom hashed structure — implementing it now means you're compatible with container/hash the day it exists. Hold off on adopting new third-party collection dependencies; the switching cost in eighteen months isn't worth it. And if you have opinions about API details — method naming, what ordered.Map should guarantee about iteration cost — the constituent proposals are open and this working group has a track record of actually incorporating feedback.
The slices and maps packages followed exactly this arc: x/exp incubation, proposal review, stdlib promotion, and near-universal adoption within two release cycles. Collections are a bigger surface area, but the process and the people are the same. This isn't a trial balloon. It's the standard library Go should have had in 2022, arriving on Go time — late, deliberate, and probably right.
Sources & further reading
- proposal: container/...: generic collection types — github.com
- proposal: container/set: new package to provide a generic set type — github.com
- Go 1.27 Release Notes (draft) — go.dev
- A plan to bring generic collections to Go 1.28 — golangweekly.com
Rachel has been embedded in the developer tooling ecosystem for nearly eight years, covering everything from IDE wars and package-manager drama to the quiet rise of AI-assisted coding. She has a soft spot for open-source maintainers and an unhealthy number of terminal emulators installed on a single laptop.
Discussion 5
finally, no more rolling my own sorted map helpers. 1.28 is forever away but at least it's official
okay this is actually huge, but i'm skeptical about the 1.28 timeline. two years for sets, ordered maps, and a heap feels wildly optimistic given how long it took just to get generics stabilized. feels like they're setting themselves up for another delay cycle.
honestly the fact this took four years after generics is funny. anyway, finally won't have to vendor a map library
yeah, the wait was rough, but i'm cautious about the 1.28 timeline. we migrated off a vendored ordered map last year when we thought this was coming sooner, and the performance characteristics ended up being totally different from what we expected in our hot path. really hoping they nail the api so we're not doing this dance again.
yeah four years is wild but honestly shipping standard collection types that everyone agrees on is harder than it looks. curious if this finally kills off the three competing third-party map libs i've got pinned