Can you store a generic function in a variable or pass it around without instantiating it?
Question 120MediumGo 1.22 to 1.25
No. A generic function is not a value until it is instantiated. There are no "generic function values", so f := Map fails with cannot use generic function Map without instantiation. You can instantiate it explicitly, or, since Go 1.21, let the context infer the type arguments when the target has a concrete function type.
func Map[T, U any](xs []T, f func(T) U) []U {
out := make([]U, 0, len(xs))
for _, x := range xs {
out = append(out, f(x))
}
return out
}
// f := Map // compile error
f := Map[int, string] // explicit instantiation
var g func([]int, func(int) string) []string = Map // Go 1.21: inferred
fmt.Println(f([]int{1, 2}, strconv.Itoa)) // [1 2]
_ = g
This also explains why you cannot write a generic closure (func[T any](x T) {} is not valid syntax) and why an interface method cannot be generic. Every function value needs one concrete signature at run time. A common workaround is to capture the type parameter from an enclosing generic function, so the closure uses T but has no type parameters of its own.
More on Generics
- Q118Which operations can you perform on a value of type parameter type? Why can't you access a struct field even when every type in the set has it?
- Q119How does type inference work? When does it fail, and how do you order type parameters to make partial instantiation pleasant?
- Q121How do you get and check the zero value of a type parameter
T? - Q122What does this print? (nil checks inside generic code)
- Q123What does this print? (type switch on a type parameter)
- Q124Why doesn't Go allow type parameters on methods? What do you do instead?