Generics in Go refer to the ability to write functions, data structures, and types that can operate on any type specified by the calling code, rather than being limited to a specific type. This allows for more flexible and reusable code. Generics enable developers to write type-safe code that works with different types without sacrificing performance or clarity.

Todo: https://go.dev/blog/intro-generics

Terminology

Type Parameters

Type parameters are placeholders for types that a function can accept. They are specified using square brackets ([]) after the function or type name. Here, T is a type parameter, any is a type constraint.

func Print[**T** name](value **T**) {
	fmt.Println(value)
}

Type Constraints

Type constraints specify what types are permissible for a type parameter. They act as meta-types for type parameters. A type parameter’s constraint typically represents a set of types, at compile time the type parameter stands for a single type. A type parameter must support all the operations the generic code is performing on it. Here, T can only be int or float64 because of the constraint int | float64.

func Add[T **int | float64**](a, b T) T {
    return a + b
}

Type Arguments

Type arguments are the actual types provided when calling code invokes a generic function. If the type argument’s type isn’t allowed by the type parameter’s constraint, the code won’t compile. Here, string is the type argument.

Print**[string]**("Hi")

Comparable

A type constraint that permits any type whose values support the == and != comparison operators.

Types that are Comparable