any vs interface{} in Go: Was ist der Unterschied?
Ethan Miller
Product Engineer · Leapcell

any
vs interface{}
in Go: Was ist der Unterschied?
In einer kürzlichen Teamdiskussion behauptete jemand: "any
und interface{}
in Go sind identisch." Technisch gesehen haben sie Recht – Go's offizielle Definition macht any
zu einem Alias für interface{}
:
type any = interface{}
Sie sind unter der Haube funktional äquivalent. Warum hat das Go-Team also any
eingeführt? Semantik und Lesbarkeit:
interface{}
: Repräsentiert "uneingeschränkte dynamische Typen" (denken Sie an JSON-Parsing, Reflektion). Betont die Dynamik, erfordert Typzusicherungen.any
: Speziell für Generics entwickelt. Markiert uneingeschränkte Typparameter und betont die typsichere Allgemeingültigkeit – sobald ein Typ festgelegt ist, bleibt er konsistent.
Diese Unterscheidung bewahrt die Abwärtskompatibilität und verdeutlicht gleichzeitig den Generics-Code.
Das Problem, das Go Generics lösen
Vor Go 1.18 (als Generics eingeführt wurden) wiederholten Entwickler Code für identische Logik mit unterschiedlichen Typen. Beispiel: Summieren von Zahlenslices:
// Sum []int64 func SumInts(numbers []int64) int64 { var s int64 for _, v := range numbers { s += v } return s } // Sum []float64 (gleiche Logik, anderer Typ) func SumFloats(numbers []float64) float64 { var s float64 for _, v := range numbers { s += v } return s }
Dies verstößt gegen DRY (Don't Repeat Yourself) und erhöht die Wartungskosten.
Go Generics: Kernkonzepte
Go 1.18 führte Generics mit 3 Schlüsselideen ein:
- Typparameter: Ermöglichen Funktionen/Typen die Verwendung parametrisierter Typen.
- Typeinschränkungen: Definieren gültige Typen für Parameter über Schnittstellen.
- Typinferenz: Leitet Typen während Aufrufen automatisch ab, was den Code vereinfacht.
Refaktorieren der Summenfunktion mit Generics
// Generische Funktion: funktioniert für int64 oder float64 func SumNumbers[T int64 | float64](numbers []T) T { var s T for _, v := range numbers { s += v } return s }
[T int64 | float64]
deklariert den Typparameter:T
ist die Typvariable,int64 | float64
ist die Union-Einschränkung.- Keine Notwendigkeit, Typen beim Aufrufen anzugeben (Compiler leitet sie ab):
ints := []int64{1, 2, 3} floats := []float64{1.1, 2.2, 3.3} fmt.Println(SumNumbers(ints)) // 6 fmt.Println(SumNumbers(floats)) // 6.6
Wiederverwendbare Typeinschränkungen
Für komplexe/wiederverwendbare Einschränkungen definieren Sie diese als Schnittstellen:
// Definieren Sie eine Einschränkung für Zahlen type Number interface { int64 | float64 } // Refaktorisiert mit benutzerdefinierter Einschränkung func SumNumbers[T Number](numbers []T) T { var s T for _, v := range numbers { s += v } return s }
Dies fördert die Lesbarkeit und Wartbarkeit.
Wie Go Generics funktionieren: Performance-Balance
Go's Generics sind dank eines einzigartigen Ansatzes effizient: GC Shape Monomorphization + Dictionaries (keine Reflektion oder v-tables):
-
GC Shape Monomorphization Der Compiler generiert Code basierend auf der "GC-Form" eines Typs (Größe, Ausrichtung, Pointer-Vorhandensein). Zum Beispiel:
int32
,uint32
,float32
teilen sich die gleiche Form (4 Bytes, keine Pointer) → Code wiederverwenden.- Alle Pointer-Typen (
*int
,*string
) teilen sich eine Form → Code wiederverwenden.
Dies vermeidet "Code Bloat" und erreicht gleichzeitig native Performance.
-
Dictionary-Technik Für Typen mit der gleichen Form, aber unterschiedlichem Verhalten (z. B.
int
vsfloat32
Addition), verwendet der Compiler versteckte "Dictionaries", um typspezifische Informationen (Methodenadressen, Operationsfunktionen) zu übergeben.
Auswirkungen in der realen Welt für Entwickler
- Nahezu native Performance: Arithmetische Operationen erreichen die Geschwindigkeit von nicht-generischem Code. Minimaler Overhead für Dictionary-basierte Methodenaufrufe (auf Augenhöhe mit Interface-Aufrufen).
- Kontrollierte Binärgröße: Code-Wiederverwendung für Typen mit gleicher "GC-Form" verhindert Bloat.
Fazit
any
und interface{}
sind technisch äquivalent, aber ihre Semantik signalisiert die Evolution von Go's Typsystem: interface{}
für dynamische Typisierung, any
für Generics. Das Verständnis dessen hilft, klareren, idiomatischeren Go-Code zu schreiben.
Leapcell: Das beste serverlose Webhosting
Empfohlene Plattform für die Bereitstellung von Go-Diensten: Leapcell
🚀 Bauen Sie mit Ihrer Lieblingssprache
Entwickeln Sie mühelos in JavaScript, Python, Go oder Rust.
🌍 Stellen Sie unbegrenzt Projekte kostenlos bereit
Zahlen Sie nur für das, was Sie nutzen – keine Anfragen, keine Gebühren.
⚡ Pay-as-You-Go, keine versteckten Kosten
Keine Leerlaufgebühren, nur nahtlose Skalierbarkeit.
🔹 Folgen Sie auf Twitter: @LeapcellHQ