Generic functions can work with multiple types while maintaining type safety.
Basic generic function
package main
import "fmt"
func Identity[T any](v T) T {
return v
}
func main() {
fmt.Println(Identity(42)) // 42
fmt.Println(Identity("hello")) // hello
}
Generic functions are type-safe because the compiler ensures type consistency:
func Add[T int | float64](a, b T) T {
return a + b
}
func main() {
sum1 := Add(10, 20) // OK: both int
sum2 := Add(3.14, 2.71) // OK: both float64
// sum3 := Add(10, 3.14) // ERROR: type mismatch
}
Generic functions with constraints
package main
import "fmt"
// Only works with numeric types
func Sum[T int | int64 | float64](numbers []T) T {
var sum T
for _, n := range numbers {
sum += n
}
return sum
}
func main() {
ints := []int{1, 2, 3, 4, 5}
fmt.Println(Sum(ints)) // 15
floats := []float64{1.1, 2.2, 3.3}
fmt.Println(Sum(floats)) // 6.6
}
Go can often infer type parameters from function arguments:
// Type parameter inferred from argument
Print(42) // T inferred as int
Print("hello") // T inferred as string
// Explicit type parameter (sometimes needed)
Print[int](42) // Explicitly specify T as int
When type inference fails
// Need explicit type when type can't be inferred
var zero T = Zero[T]() // Must specify T