Generics
Generics are a powerful feature introduced in Go 1.18 that empowers developers to write versatile and reusable code that operates on different data types. Generics provide a new level of expressiveness and flexibility to the language, allowing the creation of functions, methods, and data structures that work seamlessly across a range of types.
Syntax and Type Parameters
In Go, generics are defined using type parameters within function and method declarations. The syntax for declaring a generic function is as follows:
func FunctionName[T TypeConstraint](params) ReturnType {
// Function body
}
T
: Represents the type parameter that can be replaced with actual types when using the function.TypeConstraint
: An optional type constraint that specifies the characteristics the type parameter must satisfy.params
: The parameters that the function accepts.ReturnType
: The type the function returns.
Type Constraints
Type constraints enable the specification of requirements for the types used with generics. Common constraints include:
comparable
: Types that can be compared using comparison operators (e.g., int, string).numeric
: Numeric types that support arithmetic operations.order
: Types that can be compared and ordered (e.g., numeric types, strings).
Benefits of Generics
- Code Reusability: Generics allow the creation of functions and data structures that can work with multiple types, reducing the need for duplicated code.
- Type Safety: Compile-time type checking ensures that generic code is type-safe and minimizes runtime errors.
- Modularity: Generics promote modular design by enabling the creation of generic components that can be adapted to various contexts.
Limitation and Considerations
- Generics are currently limited to functions and methods. They cannot be used with structs or interfaces.
- Generics in Go 1.18 have some differences compared to generics in other programming languages.
- Proper documentation and clear naming of type parameters are essential for code readability.
Example
This code demonstrates a versatile function called GenericMap
that applies given functions to items in a list of various types.
package mainimport ("fmt")// GenericMap is a versatile function that applies another function to each item in a list.func GenericMap[T any, U any](list []T, f func(T) U) []U {result := make([]U, len(list))for i, item := range list {result[i] = f(item)}return result}func main() {// Mapping integers to their squaresintList := []int{1, 2, 3, 4, 5}squaredList := GenericMap(intList, func(x int) int {return x * x})fmt.Println("Squared integers:", squaredList)// Mapping strings to their lengthsstringList := []string{"apple", "banana", "cherry"}lengthList := GenericMap(stringList, func(s string) int {return len(s)})fmt.Println("String lengths:", lengthList)// Mapping floats to their square rootsfloatList := []float64{1.0, 2.0, 3.0, 4.0, 5.0}sqrtList := GenericMap(floatList, func(x float64) float64 {return math.Sqrt(x)})fmt.Println("Square roots:", sqrtList)}
GenericMap
can take a list of numbers or words and give a new list where each number is replaced by its square or length, respectively.
This example results in the following output:
Squared integers: [1 4 9 16 25]String lengths: [5 6 6]Square roots: [1 1.4142135623730951 1.7320508075688772 2 2.23606797749979]
Contribute to Docs
- Learn more about how to get involved.
- Edit this page on GitHub to fix an error or make an improvement.
- Submit feedback to let us know how we can improve Docs.