Hintergrund:
In Go gibt es standardmäßig keine allgemeinen Container wie generische Maps — erst seit Go 1.18 gibt es Generics, aber für dynamische Strukturen wird häufig map[string]interface{} verwendet, was das Speichern von Werten beliebigen Typs unter einem Zeichenfolgenschlüssel ermöglicht.
Problem:
Dieses Muster — das Äquivalent eines Wörterbuchs/JSON-Objekts — wird häufig für die Serialisierung, die Arbeit mit Middleware und Daten ohne festgelegte Struktur (z. B. JSON-Parser über encoding/json) verwendet. Der Zugriff auf Werte erfordert jedoch manuelle Typumwandlung und Vorsicht im Umgang mit impliziten Werten und fehlenden Schlüsseln.
Lösung:
Verwenden Sie map[string]interface{}, wenn die Struktur der Eingabedaten unbekannt ist. Überprüfen Sie sorgfältig das Vorhandensein eines Schlüssels und führen Sie die Typumwandlung (Type Assertion) nur nach der exists-idiom durch. Es ist besser, solche Maps nicht "tief" in der Geschäftlogik zu halten, sondern sie als Adapter an den Schnittstellen des Systems zu verwenden.
Codebeispiel:
obj := map[string]interface{}{ "int": 42, "str": "hallo", "flag": true, } if v, ok := obj["int"]; ok { n, success := v.(int) if success { fmt.Println(n) } }
Wichtige Merkmale:
Kann man ohne Fehler auf einen Wert in map[string]interface{} zugreifen, wenn der Schlüssel fehlt?
Nein, das gibt den "Zero Value" (nil) für interface{} zurück; eine Typumwandlung zu einem konkreten Typ führt zu einer Panik.
Was passiert bei der Serialisierung von map[string]interface{} mit verschachtelten Slices oder anderen Maps?
Die JSON-Serialisierung verarbeitet die Struktur korrekt, aber wenn es Typen gibt, die nicht standardmäßig unterstützt werden (wie Channels, Funktionen), tritt ein Marshaling-Fehler auf.
Kann man zwei Werte in map[string]interface{} mit == vergleichen?
Nein, interface{} kann nur verglichen werden, wenn der zugrunde liegende Wert vergleichbar ist. Wenn dort eine Map oder ein Slice vorhanden ist, gibt es eine Panik beim Vergleich.
In der Anwendung basiert die gesamte Logik auf Objekten vom Typ map[string]interface{}, jeder Controller/Dienst übergibt sie tief in den Aufrufen.
Vorteile:
Nachteile:
Verwenden Sie map[string]interface{} nur für die Arbeit mit externen Schnittstellen, Eingabe-/Ausgabedaten, und konvertieren Sie dann in normale Strukturen.
Vorteile:
Nachteile: