// syntaxfunc name[T contraint1, U constraint2 | constraint3](a T, b U) T { // defines generics T that must implement constraint1 // and U which must implement either constraint2 or constraint3 // returns type T}// examplefunc IsEqual[T comparable](a, b T) bool { return a == b}func main() { IsEqual(1, 2) // false IsEqual("a", "a") // true IsEqual[uint8](4, 4) // true (uses unsigned integers)}
Creating a constraint
// defines a constrainttype Integers32 interface { int32 | uint32}type MyInt uint32// works for either unit32 or int32, NOT MyIntfunc Sum[T Integers32](arr []T) T { var sum T for _, num := range arr { sum += num } return sum}// approximationtype ApproxIntegers32 interface { ~int32 | ~uint32}// works for MyInt, and other types that are at base either int32 or uint32func Sum[T ApproxIntegers32](arr []T) T { var sum T for _, num := range arr { sum += num } return sum}
Generic structures
type MyArr[T constraints.Ordered] struct { arr []T}func (a *MyArr[T]) max() T { if len(a.arr) < 1 { panic("Must have an non-empty array") } var max T = a.arr[0] for _, val := range a.arr { if max < val { max = val } } return max}func main() { myarr := MyArr[int]{[]int{1, 2, 3, 4}} myarr.max() // returns 4}