Go

What is a constraint in Go generics? Show the different ways to write one, including the [P *C] parsing gotcha.

Question 114MediumGo 1.22 to 1.25

A constraint is an interface that limits which type arguments are allowed. Since Go 1.18 an interface defines a type set. It can list methods, type terms (int | string), approximation terms (~int), or a mix of these.

type Number interface {
    ~int | ~int64 | ~float64
}

func Sum[T Number](xs []T) T { var s T; for _, x := range xs { s += x }; return s }

// Inline constraint; interface{ ... } may be omitted around a single union
func Abs[T ~int | ~float64](x T) T { if x < 0 { return -x }; return x }

// Methods + type terms together
type StringerInt interface {
    ~int
    String() string
}

Gotcha: in a generic type declaration, type T[P *C] struct{} is ambiguous. The parser can read it as an array length expression P * C. To fix it, wrap the constraint in interface{} or add a trailing comma:

type Ptr[P interface{ *int }] struct{ p P } // OK
type Ptr2[P *int,] struct{ p P }           // OK: trailing comma

any is an alias for interface{}. It is the most permissive constraint, and with it only operations valid for all types are allowed: assignment, passing the value, and conversion to any.

More on Generics

All 36 Generics questions