Backend Development 13 min read

An Introduction to Generics in Go

Go introduced generics in version 1.18, allowing developers to write reusable, type‑safe code by defining type parameters and constraints in square brackets, instantiating them with concrete type arguments, and using generic functions, types, and collections such as stacks and sets to improve readability, safety, and maintainability.

DeWu Technology
DeWu Technology
DeWu Technology
An Introduction to Generics in Go

Generics are a powerful feature that allows writing reusable, type‑safe code. Go added generics in version 1.18.

In Go, a type parameter is declared in square brackets after the function or type name, e.g. func Test[T any](x T) . A type argument supplies a concrete type when the generic is instantiated, e.g. Test[int](3) .

Key concepts:

Type parameter : placeholder type in generic definitions.

Type argument : concrete type used to replace a parameter.

Type parameter list : list of parameters, e.g. [T any, U any] .

Type constraint : limits the set of types a parameter can accept, e.g. T comparable .

Instantiation : generation of a concrete type from a generic definition.

Generic type , generic receiver , generic function .

Example of a generic function that prints the type of its argument:

package main

import "fmt"

// Define generic function
func PrintType[T any](x T) {
    fmt.Printf("Type: %T\n", x)
}

func main() {
    PrintType[int](42)      // Type: int
    PrintType[string]("hi") // Type: string
}

Example of a generic slice‑search function:

func Find[T comparable](slice []T, value T) int {
    for i, v := range slice {
        if v == value {
            return i
        }
    }
    return -1
}

Example of a generic stack implementation:

type Stack[T any] struct {
    data []T
}

func (s *Stack[T]) Push(v T) {
    s.data = append(s.data, v)
}

func (s *Stack[T]) Pop() (t T, err error) {
    if len(s.data) == 0 {
        return t, errors.New("stack is empty")
    }
    res := s.data[len(s.data)-1]
    s.data = s.data[:len(s.data)-1]
    return res, nil
}

Go implements generics via compile‑time type substitution (code generation), which differs from Java, C++ or C# that use type erasure or templates. Compared aspects include syntax simplicity, implementation method, type constraints, and performance.

Practical use cases include generic collections such as a Set:

type Set[T comparable] struct {
    m map[T]struct{}
}

func (s *Set[T]) Add(t T) { s.m[t] = struct{}{} }
func (s *Set[T]) Remove(t T) { delete(s.m, t) }
func (s *Set[T]) Exist(t T) bool { _, ok := s.m[t]; return ok }
func (s *Set[T]) List() []T { /* ... */ }

Advantages of Go generics:

Greater reusability – one algorithm works for many types.

Compile‑time safety – the compiler checks type correctness.

Improved readability – less boilerplate.

In summary, Go’s generic support, introduced in 1.18, enhances the language’s expressiveness, safety, and maintainability while keeping the syntax lightweight.

programmingGoExample Codegenericstype-parameters
DeWu Technology
Written by

DeWu Technology

A platform for sharing and discussing tech knowledge, guiding you toward the cloud of technology.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.