Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

Go generic types allow developers to define functions, structs, interfaces, and methods using placeholder types, known as type parameters. Resolved at compile time, generics enable the abstraction of type details while maintaining strict, static type safety, eliminating the need for runtime type assertions or the empty interface{}.

Syntax and Declaration

Type parameters are declared using square brackets [] immediately following the identifier of the function or type. Every type parameter must be bound by a type constraint. Generic Function:
func Process[T any](input T) T {
    return input
}
Generic Struct:
type Container[T any] struct {
    Value T
}

Type Constraints and Type Sets

A type constraint is an interface that defines the permissible set of types (the type set) that can satisfy a type parameter. Go 1.18 introduced new syntax to interfaces specifically for this purpose.
  • any: An alias for interface{}, representing an unconstrained type set.
  • comparable: A built-in constraint satisfied by types that support the == and != operators (e.g., booleans, numbers, strings, pointers, channels).
  • Union Elements (|): Used to define a constraint that accepts a specific list of types.
  • Approximation Elements (~): Restricts the type set to all types whose underlying type matches the specified type.
// Custom constraint using a type set
type Numeric interface {
    ~int | ~float64 // Accepts int, float64, and any derived types (e.g., type MyInt int)
}

func Add[T Numeric](a, b T) T {
    return a + b
}

Instantiation

Instantiation is the process of substituting type parameters with concrete type arguments. This occurs in two steps:
  1. Substituting the type arguments for the type parameters.
  2. Verifying that each type argument satisfies its corresponding constraint.
// Explicit type instantiation
var c Container[string]
c.Value = "Go"

// Explicit function instantiation
result := Add[int](5, 10)

Type Inference

To reduce verbosity, the Go compiler employs type inference during function calls. If the type arguments can be deduced from the regular function arguments, explicit instantiation can be omitted.
// The compiler infers [int] from the arguments (5, 10)
result := Add(5, 10) 
Note: Type inference applies only to functions. Generic types (structs, interfaces, maps, slices) always require explicit type arguments upon initialization.

Generic Methods

Methods can be declared on generic types. The receiver must declare the type parameters exactly as they are defined on the base type. However, methods themselves cannot introduce new type parameters; only top-level functions can.
type List[T any] []T

// T is bound to the receiver's type parameter
func (l *List[T]) Push(value T) {
    *l = append(*l, value)
}

Compilation Mechanics (Stenciling)

Go implements generics primarily through a process called stenciling (monomorphization), occasionally combined with dictionary passing to optimize binary size. When a generic function or type is instantiated with a concrete type, the compiler generates a distinct, type-specific copy of the code. This ensures that generic code executes with the same memory layout and performance characteristics as manually written, type-specific code, avoiding the runtime overhead associated with interface boxing and dynamic dispatch.
Master Go with Deep Grasping Methodology!Learn More