Generics, and when not to · 3 MIN READ

A constraint is an interface with types in it

Constrain a type parameter to what your code actually needs.

A constraint says what the compiler may assume about T. It is written as an interface — the same keyword — but an interface used as a constraint can list types as well as methods:

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

The | is a union, and the ~ means "any type whose underlying type is this", so type Celsius float64 satisfies ~float64. Without the tilde your own named types are excluded, which is almost never what you meant.

The standard library provides cmp.Ordered for types that support ordering. constraints is not a standard-library package. Reaching for cmp.Ordered before writing your own is useful, because a constraint is part of your API and a homemade one is a second vocabulary for readers to learn.

SEE THE IDEA

The type set controls the operations you may use

  1. 01

    Exact member

    go
    int

    Allows the predeclared int type

  2. 02

    Underlying member

    go
    ~int

    Also allows named types based on int

  3. 03

    Union

    go
    type Number interface { … }

    Allows ~int or ~float64; every member must support the operation

A type-set interface can be a constraint without being usable as an ordinary value type.

In practice

Choose the smallest useful type set for the algorithm. Use cmp.Ordered for ordering and comparable when equality or map keys are needed. The tilde permits named types with the given underlying type. Constraints with type terms belong in type-parameter positions, not in ordinary variables.

Watch out

constraints is not a standard-library package. The experimental golang.org/x/exp/constraints package is a separate dependency.

Official reference ↗

Work through the exercise

go
package main

// Sum should add up a slice of any numeric type and return the same
// type it was given. Define whatever constraint it needs.

func main() {
	println(Sum([]int{1, 2, 3}))
}
Try it yourself

Trace each value and write down your reasoning. Copy the source into GopherForge or your local Go environment to compile and check it. This web page does not execute your code or send it to a compiler service.

Progress stays in this browser. No account needed.