Lesson 9 · Methods, interfaces & generics
Generics
Type parameters — and the interview question "generics or an interface?"
Your win: read and write a generic function, explain what a constraint is, and answer the question interviewers actually care about — when to reach for generics instead of an interface.
A function parameterised by a type
Since Go 1.18, functions and types can take type parameters
in square brackets. A constraint (an interface, or the built-ins
any / comparable) says which types are allowed.1
Our sliceutils is the cleanest example:
func Map[T any, R any](in []T, f func(T) R) []R { ... } // :38
func Filter[T any](in []T, keep func(T) bool) []T { ... } // :64
func Contains[T comparable](s []T, v T) bool { ... } // :123, needs ==
// Instantiated with type inference — looks like any call:
ids := sliceutils.Map(emails, func(e *Email) string { return e.EmailID.String })
comparable on Contains is a constraint doing real work: it
permits only types you can compare with ==, so the compiler rejects, say,
a slice of func values.
The bootstrap framework is generic over your config
The other pattern in our repo: generics let one framework work with each service's
own config type T without falling back to interface{}
and casts.
type KafkaServicer[T any] interface {
InitKafkaConsumers(context.Context, T, *Resources) error
}
type bootstrapper[T any] struct { config *T; ... }
func RegisterJob[T any](name string, s JobFunc[T]) *JobBuilder[T] { ... }
T end-to-end — no
interface{}, no runtime casts. Both avoid the pre-1.18 tax of losing type
safety.
The interview question: generics or interface?
interface{} + a type assertion, you probably want generics.
Concretely: our repository ports are interfaces (each adapter behaves
differently — hits a different table). sliceutils.Map is generic (the loop
is the same for every element type). Naming that split is a strong senior-level answer.
The Go Blog — "An Introduction To Generics" + "When To Use Generics"
The official pair: the first teaches the syntax, the second answers the interview question directly. Then the Tour's generics section for hands-on.
→ go.dev/blog/intro-generics
→ go.dev/blog/when-generics ·
Tour — generics
Check yourself (from memory)
Q1. A constraint like comparable on a type parameter specifies…
comparable
allows only ==-comparable types, so Contains can use ==.
Q2. Generics are the right tool when…
Map). Different behaviour per type → interface.
Q3. Why is bootstrap declared as KafkaServicer[T any]?
T is the service's own config type,
carried type-safely end-to-end — no interface{}, no casts.
Map/Filter/Contains — keeping compile-time
type safety without interface{} + casts. Our repo: ports = interfaces,
sliceutils = generics.%w-vs-%v bug hiding in our own handlers.
1. The Go Blog — An Introduction To Generics; Go spec — type parameters.