๐ŸŽ“ A1Learner
๐Ÿ”
0 of 28 lessons completed

Go Type Sets

A type set is the group of types a constraint allows. A generic function can name a whole set at once instead of naming one fixed type.

The same job written twice

Two copies of Double do the same job for two types. Each new type would need another copy.

package main

import "fmt"

func DoubleInt(n int) int {
	return n * 2
}

func DoubleFloat(f float64) float64 {
	return f * 2
}

func main() {
	fmt.Println(DoubleInt(21))
	fmt.Println(DoubleFloat(2.5))
}

One function over a type set

The Number constraint lists int and float64 with a | sign. The ~ sign lets the named type Degrees in through its underlying float64 type.

package main

import "fmt"

type Number interface {
	~int | ~float64
}

type Degrees float64

func Double[T Number](v T) T {
	return v * 2
}

func main() {
	fmt.Println(Double(21))
	fmt.Println(Double(2.5))
	fmt.Println(Double(Degrees(15)))
}

A constraint that demands a method

The Ordered constraint demands a Compare method. Score has that method, so Max can pick the larger of two scores.

package main

import "fmt"

type Ordered[T any] interface {
	Compare(T) int
}

type Score int

func (s Score) Compare(other Score) int {
	if s < other {
		return -1
	}
	if s > other {
		return 1
	}
	return 0
}

func Max[T Ordered[T]](a, b T) T {
	if a.Compare(b) >= 0 {
		return a
	}
	return b
}

func main() {
	fmt.Println(Max(Score(7), Score(12)))
	fmt.Println(Max(Score(20), Score(9)))
}

Example

package main

import "fmt"

type Number interface {
	~int | ~float64
}

func Sum[T Number](values []T) T {
	var total T
	for _, v := range values {
		total += v
	}
	return total
}

func main() {
	fmt.Println(Sum([]int{1, 2, 3}))
	fmt.Println(Sum([]float64{1.5, 2.5}))
}

Key points

  • A constraint can list several types with the | sign.
  • The ~ sign in a constraint means the underlying type, so named types join the set.
  • One generic function over a type set serves every type in the set.
  • A constraint can also demand a method, and only types with that method fit.
  • The Ordered constraint uses T inside itself, so a type must compare against its own kind.

In this example, Sum takes a slice of any type in the Number set. The first call adds ints and prints 6. The second call adds float64 values and prints 4, with no second copy of the function.

Note

A value outside the set is refused at compile time.

Try it Yourself

Edit the code, then press Run.

Running is simulated ยท Go Playground

Exercise

What does the ~ sign do in a constraint?