liveBook · Manning

Generics

As explained in Learn Go with Pocket-Sized Projects

A parameterized type is a type declaration that includes type parameters and can be instantiated with concrete types.

Suppose a cache must accept phone numbers as keys and names as values, but another cache needs years as keys and collections of medalists as values. Generics let one type declaration serve both cases without giving up type-specific keys and values. section 7.1 section 7.1.3

A type parameter is a placeholder whose concrete type is set when the generic function or type is used. Declare parameters in square brackets: `func prettyPrint[T any](t T)` accepts a value of type `T`. The constraint `any` permits any type, so printing it with `%v` works for both a number and a string; `%f` would assume a floating-point value. Callers can specify a type explicitly, or the compiler can infer it from a function argument. section 7.1.1 section 7.6

Listing 7.1 cache.go
// Cache is key-value storage.
type Cache[K comparable, V any] struct {
    data  map[K]V
}

The cache declaration shows why different parameters can need different constraints: `K comparable` allows keys in `map[K]V`, while `V any` leaves values unrestricted. section 7.1.3

Choose a constraint for the operations the code must perform. `comparable` permits equality comparisons; an ordered constraint permits ordering comparisons. An interface can also constrain a parameter to types with a required method, as with `fmt.Stringer`, or list permitted underlying types using `~`. A parameterized slice type such as `Group[T any] []T` can have methods that use `T`. section 7.1.1 section 7.6

For the cache, initialize the map in `New[K, V]`, then add methods to read, upsert, and delete entries. Decide whether the map stores `V` or `*V`: the choice affects copying, pointer use, and how values can be updated. Generic parameters do not settle the separate requirement that a shared cache be concurrency safe. Use generics where they remove repetition, not merely because they are available. section 7.1.3 section 7.0

How Learn Go with Pocket-Sized Projects covers it

How deep it goes
Works through type parameters, inference, constraints, and a parameterized cache; treats concurrency safety as a separate implementation requirement.
Examples
Shows a parameterized printing function, a generic slice type, and a cache with comparable keys and unrestricted values.
What it assumes
Starts from Go's explicit types, then teaches type parameters and constraints before applying them to a map-backed cache.
What you can do after
Build it from scratch: declare a parameterized Go cache with appropriate constraints, an initializing constructor, and key-value methods.
How it connects
Connects type constraints and type inference to maps, interfaces, caching, and concurrency safety.

Also explained in

Compare how 20 books explain generics →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Go with Pocket-Sized Projects. The section links point to the parts of the book it draws on.