Generics with type sets is a powerful system for creating universal code.
1// Type set with union2type Signed interface {3 ~int | ~int8 | ~int16 | ~int32 | ~int644}56type Unsigned interface {7 ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint648}910type Integer interface {11 Signed | Unsigned12}1314// Function with constraint15func Abs[T Signed](n T) T {16 if n < 0 {17 return -n18 }19 return n20}2122// ~int includes all types based on int23type MyInt int24Abs(MyInt(-5)) // Works!2526// Generic struct with constraints27type Number interface {28 ~int | ~float64 | ~float3229}3031type Stats[T Number] struct {32 values []T33}3435func (s *Stats[T]) Add(v T) {36 s.values = append(s.values, v)37}3839func (s *Stats[T]) Average() float64 {40 var sum float6441 for _, v := range s.values {42 sum += float64(v)43 }44 return sum / float64(len(s.values))45}4647// Usage48s := &Stats[int]{}49s.Add(10)50s.Add(20)51fmt.Println(s.Average()) // 155253// Comparable for map keys54func Keys[K comparable, V any](m map[K]V) []K {55 keys := make([]K, 0, len(m))56 for k := range m {57 keys = append(keys, k)58 }59 return keys60}
Key concepts:
~T — type and all types based on it.| — union (any of the types).comparable — can compare with == and !=.