Goadvancedgo1.18

Generics (type parameters)

Write one function that works for many types, checked at compile time.

Go 1.18 added type parameters and constraints β€” generic Map/Filter/Reduce, comparable lookups, and reusable containers, all statically type-safe with zero reflection.

Type parameters and constraints

A type parameter is a placeholder for a type that the caller (or the compiler) fills in. You declare it in square brackets after the function name: func Max[T cmp.Ordered](a, b T) T. The cmp.Ordered part is a constraint β€” an interface that restricts which types T may be. Here it limits T to types that support <, >, and the other ordering operators.

Constraints are just interfaces, but generics let an interface list type sets (with the ~ and | syntax) in addition to methods. ~int means "any type whose underlying type is int", so your own type Celsius float64 still satisfies a ~float64 constraint. The blank constraint any (an alias for interface{}) imposes no restriction at all.

comparable and inference

The predeclared constraint comparable matches every type usable with == and != β€” exactly the types that can be a map key. Use it for membership tests (Contains), set keys, and de-duplication. It is strictly narrower than any: slices, maps, and funcs are not comparable and won't satisfy it.

You rarely write the type arguments by hand. Go infers them from the values you pass: Max(3, 7) deduces T = int, and Map(nums, strconv.Itoa) deduces both T and U from the slice and the function. You only spell them out (Max[float64](a, b)) when inference can't.

Generic data structures

Type parameters also go on types. type Stack[T any] struct { items []T } is one definition that yields a Stack[int], a Stack[string], or a Stack[User] β€” each fully type-checked, with no interface{} boxing and no runtime casts. Methods on a generic type reuse the receiver's parameter (func (s *Stack[T]) Push(v T)); they cannot introduce new type parameters of their own.

Try it 5 examples

Generic Max with an ordered constraint

Gointro
0ms
72.5pear10
Reference Β· output compiled offline, not runnable in-browser

One Max body serves int, float64, and string β€” the compiler picks T from each call, so "apple" vs "pear" is decided by lexicographic byte order (pear wins). The cmp.Ordered constraint is what permits the > comparison; an unconstrained any would not compile.