Why Go’s any and interface{} Are the Same… But Not Quite
Why Go’s any and interface{} Are the Same… But Not Quite
Leapcell: The Best Serverless Web Hosting
any
vs interface{}
in Go: What's the Difference?
In a recent team discussion, someone claimed "any
and interface{}
in Go are identical." Technically, they're right—Go's official definition makes any
an alias for interface{}
:
type any = interface{}
They're functionally equivalent under the hood. So why did the Go team introduce any
? Semantics and readability:
interface{}
: Represents "unconstrained dynamic types" (think JSON parsing, reflection). Emphasizes dynamism, requires type assertions.any
: Designed specifically for generics. Marks unconstrained type parameters, emphasizing type-safe generality—once a type is set, it stays consistent.
This distinction preserves backward compatibility while clarifying generics code.
The Problem Go Generics Solve
Before Go 1.18 (when generics arrived), developers repeated code for identical logic with different types. Example: summing number slices:
// Sum []int64
func SumInts(numbers []int64) int64 {
var s int64
for _, v := range numbers { s += v }
return s
}
// Sum []float64 (same logic, different type)
func SumFloats(numbers []float64) float64 {
var s float64
for _, v := range numbers { s += v }
return s
}
This violates DRY (Don't Repeat Yourself) and increases maintenance costs.
Go Generics: Core Concepts
Go 1.18 introduced generics with 3 key ideas:
Type Parameters: Let functions/types use parameterized types.
Type Constraints: Define valid types for parameters via interfaces.
Type Inference: Automatically deduces types during calls, simplifying code.
Refactoring the Sum Function with Generics
// Generic function: works for int64 or float64
func SumNumbers[T int64 | float64](numbers []T) T {
var s T
for _, v := range numbers { s += v }
return s
}
[T int64 | float64]
declares the type parameter:T
is the type variable,int64 | float64
is the union constraint.No need to specify types when calling (compiler infers them):
ints := []int64{1, 2, 3}
floats := []float64{1.1, 2.2, 3.3}
fmt.Println(SumNumbers(ints)) // 6
fmt.Println(SumNumbers(floats)) // 6.6
Reusable Type Constraints
For complex/reusable constraints, define them as interfaces:
// Define a constraint for numbers
type Number interface {
int64 | float64
}
// Refactored with custom constraint
func SumNumbers[T Number](numbers []T) T {
var s T
for _, v := range numbers { s += v }
return s
}
This boosts readability and maintainability.
How Go Generics Work: Performance Balance
Go's generics are efficient thanks to a unique approach: GC Shape Monomorphization + Dictionaries (not reflection or v-tables):
GC Shape Monomorphization The compiler generates code based on a type's "GC shape" (size, alignment, pointer presence). For example:
int32
,uint32
,float32
share the same shape (4 bytes, no pointers) → reuse code.All pointer types (
*int
,*string
) share a shape → reuse code.
This avoids "code bloat" while matching native performance.
Dictionary Technique For types with the same shape but different behavior (e.g.,
int
vsfloat32
addition), the compiler uses hidden "dictionaries" to pass type-specific info (method addresses, operation functions).
Real-World Impact for Developers
Near-Native Performance: Arithmetic operations match non-generic code speed. Minimal overhead for dictionary-based method calls (on par with interface calls).
Controlled Binary Size: Code reuse for same "GC shape" types prevents bloat.
Conclusion
any
and interface{}
are technically equivalent, but their semantics signal Go's type system evolution: interface{}
for dynamic typing, any
for generics. Understanding this helps write clearer, more idiomatic Go.
Leapcell: The Best Serverless Web Hosting
Recommended platform for deploying Go services: Leapcell
🚀 Build with Your Favorite Language
Develop effortlessly in JavaScript, Python, Go, or Rust.
🌍 Deploy Unlimited Projects for Free
Only pay for what you use—no requests, no charges.
⚡ Pay-as-You-Go, No Hidden Costs
No idle fees, just seamless scalability.
🔹 Follow on Twitter: @LeapcellHQ