Skip to content

When to use generics

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 any and type assertions? no – still consider interface).
  • The function only needs to call methods – use an interface instead.

Compare generic vs interface approach.

package main
import "fmt"
// Generic approach – works for any type that supports Stringer
func PrintGeneric[T fmt.Stringer](items []T) {
for _, item := range items {
fmt.Println(item.String())
}
}
// Interface approach – also works, but requires explicit satisfaction
type 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
}
Terminal window
Alice
Bob
Alice
Bob