Type Parameters
Go 1.18 added generics (type parameters). They let you write functions and types that work with any type while maintaining type safety:
// Before generics: separate functions for each type
func MinInt(a, b int) int { if a < b { return a }; return b }
func MinFloat(a, b float64) float64 { if a < b { return a }; return b }
// With generics: one function for all comparable types
func Min[T constraints.Ordered](a, b T) T {
if a < b { return a }
return b
}
fmt.Println(Min(3, 7)) // 3 (int)
fmt.Println(Min(3.14, 2.71)) // 2.71 (float64)
fmt.Println(Min("a", "b")) // "a" (string)
Constraints
| Constraint | Allows |
|---|---|
any | Any type |
comparable | Types supporting == and != |
constraints.Ordered | Types supporting < > <= >= |
constraints.Integer | All integer types |
Generic Data Structures
type Stack[T any] struct {
items []T
}
func (s *Stack[T]) Push(item T) { s.items = append(s.items, item) }
func (s *Stack[T]) Pop() (T, bool) {
if len(s.items) == 0 {
var zero T
return zero, false
}
item := s.items[len(s.items)-1]
s.items = s.items[:len(s.items)-1]
return item, true
}
intStack := Stack[int]{}
intStack.Push(1)
intStack.Push(2)
val, _ := intStack.Pop() // 2
Key Takeaway: Use generics for data structures (Stack, Queue, Set) and utility functions (Min, Max, Contains, Filter). Don't use generics when interfaces work fine — keep it simple.
Practice Exercises
Hard Production Scenario
Design a solution using these concepts for a real-world production system.
Hard Performance Analysis
Benchmark two different approaches and explain which is better and why.