Go

When should you use any (interface{}), and when are generics the better choice?

Question 92MediumGo 1.22 to 1.25

any is an alias for interface{} (Go 1.18). Every type satisfies it, which is why it throws away static type information. Legitimate uses:

  • Truly heterogeneous data: fmt.Println(args ...any), decoded JSON (map[string]any), context.WithValue, loggers.
  • Reflection-driven APIs: encoding/json, database/sql scanning.

Use generics when the same algorithm works on many types and those types relate to each other, for example so that the output type matches the input type:

// any: caller must assert, errors at runtime, boxing allocations
func MaxAny(xs []any) any { /* ... type switch ... */ return nil }

// generics: type-safe, no boxing, no assertions
func Max[T cmp.Ordered](xs ...T) T {
    m := xs[0]
    for _, x := range xs[1:] {
        m = max(m, x)
    }
    return m
}

fmt.Println(Max(3, 7, 2))        // 7
fmt.Println(Max("go", "rust"))   // rust

Gotchas:

  • A []string is not a []any. You must copy element by element, because the two have different memory layouts.
  • Numbers decoded from JSON into any come back as float64.
  • Putting non-pointer values in any usually allocates.

Rule of thumb: if you find yourself writing type switches over a fixed set of types, you probably want generics or a real interface with methods.

More on Interfaces, Methods & Embedding

All 35 Interfaces, Methods & Embedding questions