Generics in Go January 16, 2026 • Syed Ghufran Hassan Generics allow you to write functions that work with any type, while still being type-safe. The main aim of generics is to achieve greater flexibility in terms of writing code with the addition of fewer lines. Generics in Golang? Generics in Go (Golang) were introduced in Go 1.18 to let you write type-safe, reusable code without duplicating logic for every data type. Type-safe means Go ensures that the wrong type of data is not used — meaning a compile-time error will occur if the types don’t match. Reusable code means you don’t need to copy/paste the same function or structure for different types again and again. Basic generics function example Without generics We would have to write separate functions to add integers and floats. func SumInt(a, b int) int { return a + b } func SumFloat(a, b float64) float64 { return a + b } With generics When we use generics then we define type parameters using square brackets [T]. With generics, we can perform these different operations using a single function. func Sum[T int | float64](a, b T) T { return a + b } Usage fmt.Println(Sum(2, 3)) // int fmt.Println(Sum(2.5, 3.1)) // float64 What is type parameters? These are placeholder types, meaning the type isn’t fixed until you actually use the function or data structure. It indicates: “This function or structure can work with any type, which you will decide when you use it. T is a generic type parameter. We write it inside square brackets [] when we want to make a function or structure generic. When you call the function, the Go compiler replaces T with the actual type. [T int | float64] T = type parameter int | float64 = type constraint Means: T can only be int or float64 Generic function with any? In Go, any is an alias for interface{}. interface{} means it can be any type. So if you write [T any], it means T can hold a value of any type (int, string, bool, float64, …). func Print[T any](value T) { fmt.Println(value) } Output will be like Print(10) --> 10 Print("hello") --> hello Print(true) --> true What are constraints in generics? A constraint is a rule that specifies which types a generic type parameter T is allowed to use. type Number interface { int | int64 | float64 } Here, Number is a custom interface. int | int64 | float64 means that if you use Number as a type parameter, only int, int64, or float64 are allowed. Generic function using constraint func Add[T Number](a, b T) T { return a + b } T Number = T can only be a Number type (int, int64, float64). a, b T = the function inputs are of type T. return a + b = this function will return the sum of both inputs. Find maximum from slice elements using generics There is a generic function that returns the maximum value from the elements of a slice. [T int | float64] = this is a type constraint, meaning T can only be int or float64. func Max[T int | float64](values []T) T { max := values[0] for _, v := range values { if v > max { max = v } } return max } We can use this function for both integers and floats. ints := []int{10, 5, 30, 2} floats := []float64{1.2, 3.4, 0.5, 2.8} fmt.Println(Max(ints)) // Output: 30 fmt.Println(Max(floats)) // Output: 3.4 Conclusion Generics in Go unlock the power of writing one function, one structure, yet handling countless types—making your code smarter, cleaner, and future-ready. Once you embrace them, you’ll never look back at duplicated logic the same way again.