GoLang Generics
Generics in GoLang are used to make something generic, i.e a same function or other data structure works with multiple data types
Let’s understand using example
Generics in Function
- We have an add function that takes two integer and return an integer
func add(a int, b int) int
- Now if we want to do addition of a float type number, then the above mentioned function will not work. And we would need to create a new same function but just with different data types.
- This is not a efficient way of doing this.
- We can use generics which makes the add function for multiple types
func add[T int | float32 | float64](a T, b T) T
- We declare T as a type of int or float32 or float64
- We can also define the type using interface
// ~ allows to use any type that are alias of "int"
// if "~" is not used than UserId type will not work
type Num interface {
~int | int32 | int64 | float32 | float64
}
func add[T Num](a T, b T) T {
return a + b
}
type UserId int
func main() {
res := add(1.1, 2.1)
fmt.Println("result is: ", res)
res1 := add(1, 2)
fmt.Println("result is: ", res1)
u1 := UserId(1)
u2 := UserId(2)
res2 := add(u1, u2)
fmt.Println("result is: ", res2)
}
- ”~” is used to allow any alias of a type
- here in Num if “~int” is not used that adding the UserId type will result int error.
Generics in Struct
- We can use the generics in struct to have composite data type in some field
// We can have generics in the struct to have any given data type in struct field
type CustomData interface {
~int | ~string | ~float32
}
type User[T CustomData] struct {
Id int
Name string
Data T
}
func StructGenerics() {
// We would need to define which type we will be using
s1 := User[string]{
Id: 1,
Name: "Pranav",
Data: "12",
}
fmt.Println(s1)
s2 := User[int]{
Id: 1,
Name: "Pranav",
Data: 12,
}
fmt.Println(s2)
}
Generics in Map
type CustomMap[T comparable, V int | string] map[T]V
func main() {
m1 := make(CustomMap[int, string])
m1[1] = "Hello"
fmt.Println(m1)
}
Generics in Mapping function
// Make a function that executes the given function and returns the result
// eg: input = [1, 2, 3] output = [2, 4, 6]
// Make it generic so it works on multiple types
func mapValues[T Num](values []T, mapFunc func(T) T) []T {
var newValues []T
for _, v := range values {
newValue := mapFunc(v)
newValues = append(newValues, newValue)
}
return newValues
}
func main() {
res := mapValues([]int{1, 2, 3}, func(a int) int {
return a * 2
})
fmt.Println(res)
res1 := mapValues([]float32{1.1, 2.1, 3.1}, func(a float32) float32 {
return a * 2
})
fmt.Println(res1)
}