๐งฉ Part 3 of the Idiomatic Go Series โ see Part 1: The Power of Idiomatic Go and Part 2: Go Naming Cheat Sheet
Generics in Go have come a long way since 1.18. Type inference got smarter, the standard library absorbed slices, maps, and cmp, and call-site noise mostly disappeared. Now, with Go 1.27, the final major piece lands, and it's the headline language change of the release: generic methods, methods that can declare their own standalone type parameters, even when the receiver type is not generic.
This cheat sheet covers all three levels of Go generics โ functions, types, and generic methods โ with practical examples, real-world stdlib patterns, and key gotchas to keep in mind.
Quick Reference Card
These three patterns form the backbone of Goโs new expressive power โ without sacrificing simplicity.
// 1. Generic Function
func PrintAnything[T any](v T) { fmt.Println(v) }
// 2. Generic Type
type Box[T any] struct { item T }
// 3. Generic Method (New in Go 1.27)
func (r Result[T]) Transform[U any](f func(T) U) Result[U] {
return Result[U]{val: f(r.val)}
}
The Big Picture
| Level | Syntax Pattern | Idiomatic Use Case |
|---|---|---|
| Generic Function | func Fn[T constraint](v T) T |
Standalone utility routines (slices, cmp, algorithms) |
| Generic Type | type Container[T any] struct { v T } |
Reusable data structures (Box[T], generic queues, caches) |
| Generic Method (Go 1.27) | func (r Result[T]) Transform[U any](f func(T) U) Result[U] |
Method-level transformations & operations on concrete types |
๐ Generic Functions
A function that works across multiple types without code duplication.
func PrintAnything[T any](value T) {
fmt.Println(value)
}
// Usage โ Go's type inference handles the call-site
PrintAnything("hello")
PrintAnything(42)
PrintAnything(3.14)
โ Tip: Type inference improvements in Go 1.21+ and 1.27 mean you rarely need to explicitly specify type arguments like
PrintAnything[string]("hello"). The compiler automatically infersTfrom the passed arguments.
๐ Generic Types
A type (such as a struct) that holds different data types based on how it is declared.
type Box[T any] struct {
item T
}
func (b Box[T]) Item() T {
return b.item
}
// Usage
b1 := Box[int]{item: 10}
b2 := Box[string]{item: "hello"}
fmt.Println(b1.Item()) // 10
fmt.Println(b2.Item()) // hello
๐ง Note: The type parameter
Tis bound to the receiver typeBox[T]. Every receiver method onBox[T]automatically gains access toTwithout needing to redeclare it.
๐ Generic Methods (New in Go 1.27)
A method that can declare its own standalone type parameters โ even if the receiver type is non-generic or requires a different type parameter. This is the headline addition in Go 1.27.
Example A: Non-Generic Receiver with Generic Method
type Player struct {
name string
}
// Method declares its own type parameter P
func (p Player) Say[P any](thing P) {
fmt.Println(p.name, "says:", thing)
}
// Usage
p := Player{name: "Mario"}
p.Say("hello") // Mario says: hello
p.Say(123) // Mario says: 123
p.Say(true) // Mario says: true
Example B: Transforming Types with Transform
Combining generic receiver types with new method type parameters enables smooth functional chaining:
type Result[T any] struct {
val T
}
// The method declares its own new type parameter U
func (r Result[T]) Transform[U any](f func(T) U) Result[U] {
return Result[U]{val: f(r.val)}
}
// Usage
res := Result[int]{val: 100}
halved := res.Transform(func(n int) int { return n / 2 })
summary := halved.Transform(func(n int) string {
return fmt.Sprintf("result=%d", n)
})
fmt.Println(summary.val) // result=50
๐ Deep Dive: Seamless Type Inference: Notice how
res.Transform(func(n int) string { ... })doesn't require explicit call-site parameterization likeres.Transform[string](...). Go's inference engine inspects the signature of the closure passed intoTransformto inferU = stringdirectly.
โ ๏ธ The Gotcha: Generic Methods and Interfaces
Interface methods cannot declare type parameters, and generic methods cannot satisfy interfaces.
type Mapper interface {
Map[U any](f func(int) U) any
}
// compile error: interface method must have no type parameters
This is a deliberate limit: Go resolves interface satisfaction at compile time, and open-ended generic dispatch would clash with that. If you need interface polymorphism across generic types, put the type parameters on the interface instead:
type Mapper[T, U any] interface {
Map(f func(T) U) U
}
๐งช Real-World Example: math/rand/v2
The standard library directly leverages generic methods in Go 1.27. For instance, math/rand/v2 equips (*Rand).N as a generic method operating on integer types, directly matching top-level helper routines:
r := rand.New(rand.NewPCG(1, 2))
fmt.Println(r.N(100)) // int in [0, 100)
Prior to Go 1.27, this call pattern required separate package-level functions. Now, it integrates directly onto the Rand concrete receiver type.
๐งต Wrapping Up
Go generics now cover the full lifecycle: functions that adapt, types that configure, and methods that extend. Go 1.27's generic methods resolve a long-standing language gap while keeping compilation fast and type safety robust.
๐ฌ How are you planning to use generic methods in your Go 1.27 projects? Are you refactoring package-level utility functions into methods on concrete types?
ย
๐ Want to go deeper?
ย
ย
ย
Top comments (4)
Whoa, this is fire! ๐ฅ
Another banger from the Idiomatic Go series โ and this 1.27 generics cheat sheet is exactly what the dev community needed.
Loved how you broke down the three tiers (functions, types, methods) so clearly, and the hands-on examples with Result.Transform and Player.Say make it super easy to grok. The gotchas section โ especially the interface limitation โ is a solid heads-up that'll save folks a ton of debugging later.
Also, big props for pulling in math/rand/v2 as a real-world example. Shows this feature is already battle-tested in the stdlib.
Keep dropping this knowledge with your signature clarity and energy. You're leveling up so many gophers out here (myself included)! Can't wait for the next drop in the series. ๐
Mad respect and huge thanks for this gem. ๐๐น
Thanks so much, I really appreciate this! ๐
Generic methods finally make the generics story feel complete, so it was fun to put this cheat sheet together. More idiomatic Go posts on the way! ๐
Great read! Go Go!
Thanks Vincent! Glad you liked it โ Go Go! ๐