Generics in Golang have been one of the most anticipated features in the language’s history. Introduced in Go 1.18, generics allow developers to write more reusable, flexible, and type-safe code. In this post, you’ll learn what generics are, how to use them, and see real-world examples to get you started.
What Are Generics in Go?
Generics let you write functions and types that work with any data type, while still providing compile-time type safety. Prior to generics, developers often used interfaces (especially interface{}
) or code duplication to achieve similar functionality—both of which come with tradeoffs in type safety and maintainability.
Why Use Generics in Golang?
- Type safety – Avoid type assertion bugs by specifying generic type constraints
- Code reuse – Write one function that works with many types
- Cleaner code – Eliminate repetitive logic for similar data structures
Basic Syntax of Generics
Let’s start with a simple example: a generic function that finds the maximum of two values.
package main import "fmt" func Max[T comparable](a, b T) T { if a > b { return a } return b } func main() { fmt.Println(Max(3, 7)) // Output: 7 fmt.Println(Max("go", "golang")) // Output: golang }
Here’s what’s happening:
[T comparable]
declares a type parameterT
with a constraint (must be comparable)Max
works with any type that supports>
(like ints, floats, and strings)
Using Type Constraints
You can define your own constraints using Go’s new interface
syntax for generics. Here’s an example that limits input to integer types.
type Number interface { int | int64 | float64 } func Add[T Number](a, b T) T { return a + b }
This constraint ensures that only numeric types are accepted by the Add
function.
Generic Structs
Generics aren’t just for functions—you can use them with structs too:
type Pair[T any] struct { First T Second T } func main() { p := Pair[string]{First: "Hello", Second: "World"} fmt.Println(p.First, p.Second) }
The any
keyword is a built-in alias for interface{}
, meaning the type can be anything.
Real-World Use Case: Generic Map Function
Here’s a more practical use case: a generic Map
function that transforms a slice using a callback function.
func Map[T any, U any](input []T, transform func(T) U) []U { result := make([]U, len(input)) for i, v := range input { result[i] = transform(v) } return result }
Example usage:
doubles := Map([]int{1, 2, 3}, func(n int) int { return n * 2 }) fmt.Println(doubles) // [2 4 6]
Common Gotchas
- Constraints matter: Without the right constraint, certain operations (like
+
,>
) won’t compile. - Don’t overuse: If you’re not writing reusable logic, stick to plain types for clarity.
- Performance: Generics are compiled statically, so performance is typically on par with non-generic code.
Resources for Learning More
Want to keep going? These tutorials and docs will help deepen your understanding of generics in Go:
- Go.dev Generics Tutorial
- Go by Example: Generics
- Intro to Generics (Go Blog)
- DigitalOcean Guide
- Mastering Generics (Medium)
Conclusion
Golang generics bring a long-awaited feature to the Go programming language—one that enhances code reusability and type safety without sacrificing performance. As more packages and libraries adopt generics, understanding them will be essential for every Go developer. Try them out in your own projects and see how they simplify your code!
Frequently Asked Questions about Golang Generics
What are generics in Golang?
Generics in Go allow you to write functions and types that work with different data types while maintaining type safety. Introduced in Go 1.18, generics use type parameters and constraints to create reusable and flexible code.
What version of Go supports generics?
Generics were officially introduced in Go 1.18. Make sure you’re using Go 1.18 or later to take advantage of this feature.
Do generics replace interfaces in Go?
No, generics and interfaces serve different purposes. Interfaces are great for abstract behavior, while generics are used for reusable functions and data structures that work across many types. In some cases, they can be used together.
Are generics in Go runtime or compile-time?
Generics in Go are compile-time. That means your code is type-checked and optimized by the compiler, leading to efficient and safe binaries.
Can I use multiple type parameters in a generic function?
Yes. You can define multiple type parameters in brackets, like [T any, U any]
, and use them throughout the function or struct as needed.
Leave a Reply