liveBook · Manning

Generics

As explained in Go in Action, Second Edition

Generic programming is a language feature that defines functions, types, and interfaces parameterized over types while preserving compile-time type safety.

When the same operation is needed for several types, copying its implementation creates boilerplate. Generics let a function, type, or interface take type parameters, so one implementation can serve different types while preserving compile-time type safety. They avoid the type assertions that type-agnostic code built around interface{} often required. section 6.0 section 6.1

func Filter[T any](items []T, keep func(T) bool) []T {
	var result []T
    for _, item := range items {
        if keep(item) {
            result = append(result, item)
        }
    }
    return result
}

A single Filter[T any] replaces separate filtering functions for recipes and steps. T appears in both the input slice and predicate, keeping their element types aligned; the compiler can infer T from a call. section 6.1

The constraint after a type parameter determines which types are accepted and which operations the implementation may use. any imposes no specific operation; comparable permits equality checks, as needed when a linked list searches for an item. Arithmetic needs an explicit constraint covering types that support it. A constraint based on an interface exposes only that interface’s methods. section 6.1 section 6.5.2 section 6.5.3

Type parameters can carry the same guarantees through larger abstractions:

  • A LinkedList[T] stores T values in nodes, implements collection operations, and can be constructed as NewLinkedList[Recipe](). section 6.1 section 6.3
  • A HashMap[K comparable, V any] keeps key and value types distinct while wrapping a built-in map. Its key constraint supports map lookup. section 6.4
  • A Transform[T any, U any] function converts a slice of one type into another—for example, extracting string titles from recipes. section 6.2
type HashMap[K comparable, V any] struct {      #1
	m map[K]V                                  #2
}

func NewHashMap[K comparable, V any]() *HashMap[K, V] {   #3
	return &HashMap[K, V]{m: make(map[K]V)}               #4
}

The constructor and struct show how K and V travel together from declaration to instantiated map storage. section 6.4

Use a generic abstraction when identical logic serves multiple types or an API must preserve type relationships. Prefer concrete code when there is only one use or the implementations differ; prefer a plain interface when behavior matters more than exact type identity. A useful check is whether two independent call sites need different type arguments. section 6.5.4

Keep performance decisions evidence-based: benchmark hot paths, avoid unnecessary interface conversions, and use a narrow constraint when operations require one. Type inference can fail or need explicit type arguments. Generic and nongeneric code can coexist, so adoption need not be a rewrite. section 6.5.1 section 6.5.3 section 6.5.5

Before writing a collection helper, check the standard library: slices offers type-safe sorting, including SortFunc with a comparator for recipe serving sizes; maps offers operations such as Equal and Keys. section 6.6.2

How Go in Action, Second Edition covers it

How deep it goes
Works through generic functions, collection interfaces, linked lists, maps, constraints, and adoption trade-offs; does not benchmark a production workload.
Examples
Uses recipe filtering and title extraction, a generic linked list and hash map, and sorting recipes by serving size.
What it assumes
Assumes familiarity with Go types and collections; teaches type parameters and constraints through progressively richer collection examples.
What you can do after
Build it from scratch: define type-safe generic collections and functions, then choose constraints and assess whether reuse warrants the abstraction.
How it connects
Connects type parameters to interfaces, linked lists, maps, type inference, type constraints, and standard-library collection utilities.

Also explained in

Compare how 20 books explain generics →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Go in Action, Second Edition. The section links point to the parts of the book it draws on.