7.3 Generic Functions

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