What problem do type parameters solve that interface{}/any parameters did not?
Question 112MediumGo 1.22 to 1.25
Before Go 1.18 you had two choices for reusable code: write it once per type (or with go generate), or accept interface{} and give up static typing. With any the compiler cannot check element types, callers need type assertions, values are boxed (often heap-allocated), and mistakes show up as runtime panics.
Type parameters let a function or type be parameterized over types. The compiler checks every instantiation, the result type is exact, and no assertions are needed.
// Pre-generics: unsafe, needs assertions
func MaxAny(a, b any) any { /* reflect or type switch */ return a }
// Generic: type-safe, no boxing for value types
func Max[T cmp.Ordered](a, b T) T {
if a > b {
return a
}
return b
}
x := Max(3, 7) // x is int
s := Max("go", "rust") // s is string
// Max(3, "a") // compile error: mismatched types
What the interviewer wants to hear: generics add compile-time type safety and remove the boxing and assertion overhead. They are meant for algorithms and containers that do not care about the element type. They are not a replacement for interfaces that model behaviour.
More on Generics
- Q113What is the difference between
func F(s fmt.Stringer)andfunc F[T fmt.Stringer](s T)? When does it matter? - Q114What is a constraint in Go generics? Show the different ways to write one, including the
[P *C]parsing gotcha. - Q115What does the
~(tilde) token mean in a constraint? What happens without it? - Q116Explain type sets. How do unions and intersections combine, and which interfaces can only be used as constraints?
- Q117What is
comparable? What changed in Go 1.20, and what does this program print? - 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?