Learn Go← Dashboard

Type parameters, constraints, and the comparable / any keywords.

Constraints

A type parameter without a constraint isn't very useful — Go won't let you do anything to it because it might be any type. Constraints describe what the type must look like.

Built-in constraints

| Constraint | Means | | ------------- | ------------------------------------------------- | | any | Anything. (Same as the empty interface.) | | comparable | Anything you can compare with == and !=. |

func In[T comparable](needle T, haystack []T) bool {
    for _, x := range haystack {
        if x == needle { return true }
    }
    return false
}
go playground
Loading...

Union types: A | B | C

You can list specific types separated by |. Either spelled inline or — usually nicer — defined as a named interface.

type Number interface {
    int | int64 | float64
}

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

Approximation: ~T

~int means "any type whose underlying type is int". That includes named types like type Celsius int.

type Integer interface {
    ~int | ~int32 | ~int64
}

Almost always use the tilde form for numeric constraints — otherwise your function rejects type MyInt int.

cmp.Ordered (Go 1.21+)

The standard library ships a cmp package with the most common shape:

package cmp

type Ordered interface {
    ~int | ~int8 | ~int16 | ~int32 | ~int64 |
        ~uint | ~uint8 | ... |
        ~float32 | ~float64 |
        ~string
}

Use cmp.Ordered for "anything I can compare with < and >". That's how slices.Sort is generic. Before Go 1.21, golang.org/x/exp/constraints provided the same thing.

go playground
Loading...
Why is `~int` (with tilde) often safer than plain `int` in a constraint?