Go🚀Advancedadvanced
Generics (Type Parameters)
Go · Advanced · Run with go run
Explanation
Generics, introduced in Go 1.18, allow functions and types to be parameterized over types. Type parameters are declared in square brackets: `func Map[T, U any](s []T, f func(T) U) []U`. Interface constraints specify what operations are valid on type parameters — `comparable` for equality, `constraints.Ordered` for comparison. The `any` constraint accepts any type.
Real-World Scenario
A generic `Filter` function works on slices of any type without code duplication: `Filter(users, func(u User) bool { return u.Active })` — same logic for `[]User`, `[]Order`, `[]Product` without writing three separate functions.
Quick Snippet
snippet.go
// Generic function
func Map[T, U any](s []T, f func(T) U) []U {
result := make([]U, len(s))
for i, v := range s {
result[i] = f(v)
}
return result
}
func Filter[T any](s []T, pred func(T) bool) []T {
var out []T
for _, v := range s {
if pred(v) { out = append(out, v) }
}
return out
}
// Generic type
type Stack[T any] struct{ items []T }
func (s *Stack[T]) Push(v T) { s.items = append(s.items, v) }
func (s *Stack[T]) Pop() (T, bool) {
if len(s.items) == 0 { var zero T; return zero, false }
v := s.items[len(s.items)-1]
s.items = s.items[:len(s.items)-1]
return v, true
}Full Example
generics.go
// Compile: go run generics.go
// Output:
// doubled: [2 4 6 8]
// evens: [2 4]
// stack push/pop: 3 2 1
package main
import "fmt"
func Map[T, U any](s []T, f func(T) U) []U {
result := make([]U, len(s))
for i, v := range s {
result[i] = f(v)
}
return result
}
func Filter[T any](s []T, pred func(T) bool) []T {
var out []T
for _, v := range s {
if pred(v) {
out = append(out, v)
}
}
return out
}
type Stack[T any] struct{ items []T }
func (s *Stack[T]) Push(v T) { s.items = append(s.items, v) }
func (s *Stack[T]) Pop() (T, bool) {
if len(s.items) == 0 {
var zero T
return zero, false
}
v := s.items[len(s.items)-1]
s.items = s.items[:len(s.items)-1]
return v, true
}
func main() {
nums := []int{1, 2, 3, 4}
doubled := Map(nums, func(n int) int { return n * 2 })
fmt.Println("doubled:", doubled)
evens := Filter(nums, func(n int) bool { return n%2 == 0 })
fmt.Println("evens:", evens)
var st Stack[int]
st.Push(1)
st.Push(2)
st.Push(3)
fmt.Print("stack push/pop:")
for {
v, ok := st.Pop()
if !ok {
break
}
fmt.Print(" ", v)
}
fmt.Println()
}
Run command
go run generics.go