Experimental and deprecated Go packages for various functionality
Package constraints provides a set of useful constraint interfaces to be used with Go generic type parameters. These constraints enable generic functions to work with specific categories of types, such as signed integers, floating-point numbers, or any ordered types.
go get golang.org/x/exp/constraintsimport (
"golang.org/x/exp/constraints"
)Alternative import pattern for specific constraints:
import (
"golang.org/x/exp/constraints"
)
// Use in type parameters
func Max[T constraints.Ordered](a, b T) T {
if a < b {
return b
}
return a
}package main
import (
"fmt"
"golang.org/x/exp/constraints"
)
// Generic function that works with any signed integer
func AddSigned[T constraints.Signed](a, b T) T {
return a + b
}
// Generic function that works with any floating-point type
func MaxFloat[T constraints.Float](a, b T) T {
if a > b {
return a
}
return b
}
// Generic function that works with any ordered type
func Min[T constraints.Ordered](a, b T) T {
if a < b {
return a
}
return b
}
func main() {
// Signed integers
result1 := AddSigned(int32(5), int32(3))
fmt.Println(result1) // 8
// Floating-point types
result2 := MaxFloat(3.14, 2.71)
fmt.Println(result2) // 3.14
// Ordered types (string)
result3 := Min("apple", "banana")
fmt.Println(result3) // apple
}Permits any signed integer type. Useful for generic functions that need to work with signed integers of any size.
type Signed interface {
~int | ~int8 | ~int16 | ~int32 | ~int64
}The Signed constraint permits any signed integer type. If future releases of Go add new predeclared signed integer types, this constraint will be modified to include them.
Use case: Generic functions performing arithmetic operations or comparisons on signed integer values.
Example:
func Sum[T constraints.Signed](values ...T) T {
var total T
for _, v := range values {
total += v
}
return total
}
// Works with any signed integer type
sum := Sum(int64(1), int64(2), int64(3))Permits any unsigned integer type. Useful for generic functions working with unsigned integers or bitwise operations.
type Unsigned interface {
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
}The Unsigned constraint permits any unsigned integer type. If future releases of Go add new predeclared unsigned integer types, this constraint will be modified to include them.
Use case: Generic functions handling unsigned values, memory offsets, or bit manipulation.
Example:
func IsPowerOfTwo[T constraints.Unsigned](n T) bool {
return n > 0 && (n&(n-1)) == 0
}
// Works with any unsigned integer type
isPower := IsPowerOfTwo(uint32(16))Permits any integer type (both signed and unsigned). This is a composite constraint combining Signed and Unsigned.
type Integer interface {
Signed | Unsigned
}The Integer constraint permits any integer type. If future releases of Go add new predeclared integer types, this constraint will be modified to include them.
Use case: Generic functions that need to work with any integer type regardless of signedness.
Example:
func Abs[T constraints.Integer](n T) T {
if n < 0 {
return -n
}
return n
}
// Works with both signed and unsigned integers
absValue := Abs(int32(-42))Permits any floating-point type. Useful for generic functions performing mathematical operations on float types.
type Float interface {
~float32 | ~float64
}The Float constraint permits any floating-point type. If future releases of Go add new predeclared floating-point types, this constraint will be modified to include them.
Use case: Generic mathematical functions, statistical calculations, or scientific computations.
Example:
func Average[T constraints.Float](values ...T) T {
var sum T
for _, v := range values {
sum += v
}
return sum / T(len(values))
}
// Works with any floating-point type
avg := Average(3.14, 2.71, 1.41)Permits any complex numeric type. Useful for generic functions working with complex numbers.
type Complex interface {
~complex64 | ~complex128
}The Complex constraint permits any complex numeric type. If future releases of Go add new predeclared complex numeric types, this constraint will be modified to include them.
Use case: Generic functions for complex number arithmetic, signal processing, or advanced mathematical operations.
Example:
func Magnitude[T constraints.Complex](c T) float64 {
r := real(c)
i := imag(c)
return math.Sqrt(r*r + i*i)
}
// Works with any complex type
mag := Magnitude(complex(3, 4))Permits any ordered type - any type that supports the comparison operators (<, <=, >=, >). This constraint enables sorting and minimum/maximum operations on any comparable ordered type.
type Ordered = cmp.OrderedThe Ordered constraint permits any ordered type. If future releases of Go add new ordered types, this constraint will be modified to include them.
Note: This type is redundant since Go 1.21 introduced cmp.Ordered. For Go 1.21+, prefer using cmp.Ordered directly.
Use case: Generic functions for sorting, finding minimum/maximum values, or other operations requiring ordering.
Example:
func Max[T constraints.Ordered](a, b T) T {
if a > b {
return a
}
return b
}
func Min[T constraints.Ordered](a, b T) T {
if a < b {
return a
}
return b
}
// Works with strings, numbers, or any comparable type
maxStr := Max("apple", "zebra")
maxInt := Max(10, 20)
minFloat := Min(3.14, 2.71)The constraints in this package form the following hierarchy:
package constraints // import "golang.org/x/exp/constraints"
// Signed is a constraint that permits any signed integer type.
type Signed interface {
~int | ~int8 | ~int16 | ~int32 | ~int64
}
// Unsigned is a constraint that permits any unsigned integer type.
type Unsigned interface {
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
}
// Integer is a constraint that permits any integer type (signed or unsigned).
type Integer interface {
Signed | Unsigned
}
// Float is a constraint that permits any floating-point type.
type Float interface {
~float32 | ~float64
}
// Complex is a constraint that permits any complex numeric type.
type Complex interface {
~complex64 | ~complex128
}
// Ordered is a constraint that permits any ordered type.
// This is equivalent to cmp.Ordered and is redundant in Go 1.21+.
type Ordered = cmp.Ordered// Clamp constrains a value to a range
func Clamp[T constraints.Ordered](value, min, max T) T {
if value < min {
return min
}
if value > max {
return max
}
return value
}
// Usage
clampedInt := Clamp(5, 1, 10) // 5
clampedStr := Clamp("b", "a", "c") // "b"// Some types might satisfy multiple constraints
// Use union syntax for functions needing specific types
// Function for numeric types that can be ordered
func LinearInterpolate[T constraints.Float](a, b, t T) T {
return a*(1-t) + b*t
}
// Function for any comparable type
func Contains[T constraints.Ordered](slice []T, value T) bool {
for _, v := range slice {
if v == value {
return true
}
}
return false
}// Calculate statistical measures
func Variance[T constraints.Float](values []T) T {
if len(values) == 0 {
return 0
}
var mean T
for _, v := range values {
mean += v
}
mean /= T(len(values))
var variance T
for _, v := range values {
diff := v - mean
variance += diff * diff
}
variance /= T(len(values))
return variance
}
// Calculate magnitude of complex numbers
func Conjugate[T constraints.Complex](c T) T {
return T(complex(real(c), -imag(c)))
}Instead of using type switches, you can use constraints to handle multiple types generically:
// Without constraints (type switch)
func PrintValue(v interface{}) {
switch val := v.(type) {
case int:
fmt.Println("int:", val)
case float64:
fmt.Println("float:", val)
case string:
fmt.Println("string:", val)
}
}
// With constraints (generic)
func PrintValue[T constraints.Ordered](v T) {
fmt.Println("value:", v)
}// Define custom constraint combinations as needed
type Numeric interface {
constraints.Integer | constraints.Float
}
func Square[T Numeric](value T) T {
return value * value
}
// Works with any integer or float type
sqInt := Square(int32(5)) // 25
sqFloat := Square(3.5) // 12.25~ in constraint definitions allows named types whose underlying type matches. For example, a custom type MyInt with underlying type int satisfies the Signed constraint.Ordered constraint is redundant in Go 1.21 and later. Use cmp.Ordered from the standard library instead for new code.Install with Tessl CLI
npx tessl i tessl/go-golang-org-x-exp