When to use generics
Context
Section titled “Context”Generics are powerful but not always necessary. Use generics when:
- You write functions that work on slices, maps, or channels of any type (e.g.,
Reverse,Map,Filter). - You need a container data structure (like a stack, queue, or tree) that works with multiple types.
- You want to avoid code duplication for similar algorithms.
Avoid generics when:
- A simple interface (with methods) would work.
- The type parameter is used only once (just use
anyand type assertions? no – still consider interface). - The function only needs to call methods – use an interface instead.
Example
Section titled “Example”Compare generic vs interface approach.
Code example
Section titled “Code example”package main
import "fmt"
// Generic approach – works for any type that supports Stringerfunc PrintGeneric[T fmt.Stringer](items []T) { for _, item := range items { fmt.Println(item.String()) }}
// Interface approach – also works, but requires explicit satisfactiontype Stringer interface { String() string}func PrintInterface(items []Stringer) { for _, item := range items { fmt.Println(item.String()) }}
type Person struct{ Name string }func (p Person) String() string { return p.Name }
func main() { people := []Person{{"Alice"}, {"Bob"}} PrintGeneric(people) // works because Person implements fmt.Stringer PrintInterface(people) // also works}Output
Section titled “Output”AliceBobAliceBob