Go Generics with Type Constraints
Go 1.18 added generics; Go 1.21 polished them with the new `cmp` and `slices` packages. This snippet shows a generic `Map`, a numeric constraint via `~int | ~float64`, and a `comparable`-bounded set type. The runnable code targets Go 1.18 syntax (no `cmp.Ordered`, no `slices.Sort`) so it compiles on as many Go versions as possible; the 1.21+ shortcuts are referenced in comments. Note: the project's test runner uses Go 1.13.5 which predates generics, so test execution is expected to FAIL there but the code is valid Go 1.18+.
236 views
3
package main
import "fmt"
// Map applies fn to every element and returns a new slice.
// Type parameters: T is the input element type, U is the output type.
func Map[T, U any](xs []T, fn func(T) U) []U {
out := make([]U, len(xs))
for i, x := range xs {
out[i] = fn(x)
}
return out
}
func main() {
nums := []int{1, 2, 3, 4}
squares := Map(nums, func(n int) int { return n * n })
fmt.Println(squares) // [1 4 9 16]
words := []string{"hello", "world"}
lengths := Map(words, func(s string) int { return len(s) })
fmt.Println(lengths) // [5 5]
}Type parameters appear in square brackets after the function name: [T, U any] introduces two parameters with the loosest possible constraint, any (alias for interface{} since 1.18). The compiler infers concrete types from the arguments at call time, so callers do not need to spell Map[int, int](...) explicitly. make([]U, len(xs)) pre-sizes the result slice for one allocation. This is the Go equivalent of Array.prototype.map in JavaScript or list comprehension in Python; before generics, the only way to write this was per-type duplication or interface{} slices with runtime assertions.
2 more snippets in this entry are available for premium members.
Upgrade to Premium