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.
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.
DeWu Technology
A platform for sharing and discussing tech knowledge, guiding you toward the cloud of technology.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.