Skip to content
Muhammet Şafak
tr
Languages 3 min read

Go 1.18 Generics: Toward the End of a Long Wait

Go 1.18's generic support shows how a language can be reshaped thoughtfully. First impressions and trade-offs.


The Go community had been debating generics for years. The topic came up at every major Go conference; design proposals arrived and faded away. Go 1.18 ships in March 2022 and finally puts a concrete answer on the table. I don’t have the release in my hands yet — I’m writing this based on pre-release notes and technical proposal documents — but there is enough clarity about what’s coming.

Generics landing in Go is not just about adding new syntax. It’s about how a feature that is in tension with one of the language’s core design principles — simplicity and explicitness — was balanced with remarkable care.

Why Go Wanted to Wait This Long

Understanding why Go held off on generics requires a look at the language’s philosophy. Rob Pike and the team treated simplicity as the prime directive. Generics is a feature that significantly increases type-system complexity in most languages. C++ templates, and the generic implementations in Java and C#, impose a real cost on both compile times and the readability of error messages.

The core question for the Go team was: how do we add generics without breaking the language’s simplicity? Years of design work went into finding that balance. The solution they landed on — type parameters and interface constraints — appears to strike that balance quite well.

Type Parameter Syntax

The syntax in 1.18 uses square brackets. An example:

func Map[T, U any](s []T, f func(T) U) []U {
    result := make([]U, len(s))
    for i, v := range s {
        result[i] = f(v)
    }
    return result
}

This function works on any slice. Previously, achieving this kind of abstraction meant either using interface{} or writing a separate function for every type. Neither option was pleasant.

The existing interface system was extended to handle constraints:

type Number interface {
    int | int64 | float64
}

func Sum[T Number](s []T) T {
    var total T
    for _, v := range s {
        total += v
    }
    return total
}

Defining constraints with type unions gives a safer and more explicit structure. The statement “this function accepts an int or a float64” now lives directly in the code.

What We Gain, What We Risk Losing

The gains are clear: boilerplate shrinks. Universal collection operations — sorting, filtering, transforming — can now be written with a single definition. The standard library will gradually start using this pattern as well.

On the other hand, there are things we risk losing. Generics can make code harder to read, especially when constraints grow complex. The Java world has seen what’s sometimes called “generic hell” — nested type parameters that render type error messages completely unreadable. Does Go’s design prevent that? Partly. But it’s still possible to write unnecessarily complex constraints.

Compile time is also debatable. Performance regressions were reported early on; that’s somewhat expected and will improve over time.

When I’ll Actually Use This in Practice

I’m not planning to use generics everywhere. One of Go’s strengths is readability; adding a type parameter to a function doesn’t automatically make it more readable. Collection helper functions, data transformation operations, type-safe data structures (stacks, queues, sets) — these are the places where generics create real value.

In team code, I’ll be more cautious. Getting value out of generics requires the team to internalize the concept; spreading them everywhere prematurely just increases the “why is this written this way?” questions.

As the release lands in people’s hands, real-world experience will come in from the community. At that point, these first impressions will need revisiting. For now, what I can say is this: Go 1.18 brings the most significant change in the language’s ten-year history, and the care with which that change was made is an interesting lesson in language design.

Tags: #Go
Share:

Comments

Sign in with your GitHub account to join the discussion. Comments are stored in GitHub Discussions.

Related Posts

Search the site

Start typing to search posts, projects and pages.

Esc to close Powered by Pagefind