Go Generics
Basic Generic Functions
Generic functions with type parameters:
// Generic function with a single type parameter
func PrintAny[T any](item T) {
fmt.Println(item)
}
// Usage
PrintAny[string]("hello")
PrintAny[int](42)
// Type inference allows omitting the type argument
PrintAny(true)
Type Constraints
Constraining type parameters with interfaces:
// Generic function with constraint
func Min[T constraints.Ordered](a, b T) T {
if a < b {
return a
}
return b
}
// Usage
min := Min[int](5, 10)
minFloat := Min(3.14, 2.71) // Type inference
Custom Constraints
Creating custom type constraints:
// Custom constraint interface
type Number interface {
int | int64 | float64 | float32
}
// Generic function with custom constraint
func Sum[T Number](values []T) T {
var result T
for _, v := range values {
result += v
}
return result
}
// Usage
ints := []int{1, 2, 3, 4, 5}
sum := Sum(ints) // 15
Generic Data Structures
Creating generic data structures:
// Generic stack
type Stack[T any] struct {
items []T
}
// Methods on generic types
func (s *Stack[T]) Push(item T) {
s.items = append(s.items, item)
}
func (s *Stack[T]) Pop() (T, error) {
var zero T
if len(s.items) == 0 {
return zero, errors.New("stack is empty")
}
index := len(s.items) - 1
item := s.items[index]
s.items = s.items[:index]
return item, nil
}
// Usage
strStack := Stack[string]{}
strStack.Push("hello")
strStack.Push("world")
item, _ := strStack.Pop() // "world"
Type Parameter Inference
Type inference in function chains:
// Generic map function
func Map[T, U any](items []T, fn func(T) U) []U {
result := make([]U, len(items))
for i, item := range items {
result[i] = fn(item)
}
return result
}
// Usage with type inference
nums := []int{1, 2, 3, 4}
squares := Map(nums, func(n int) int {
return n * n
})
// squares = [1, 4, 9, 16]
Best Practices for Generics
- Use generics when there’s a clear need for type parameterization
- Prefer the narrowest possible constraint that works for your use case
- Use
any
constraint when you need to accept all types - Import
golang.org/x/exp/constraints
for common constraints (Go 1.18+) - Remember that type parameters are resolved at compile time