Jagd auf Schlüssel: Wie man sich im Dickicht der Go-Map nicht verliert
\nStellen Sie sich vor: Sie schreiben einen Microservice in Go. Sie müssen schnell prüfen, ob ein Benutzer im System registriert ist. Sie greifen auf eine Map zu, in der der Schlüssel die Benutzer-ID und der Wert das Profil ist. Und dann stellt sich die Frage: Gibt es diesen Schlüssel überhaupt in der Map?
\nWenn Sie von Python oder JavaScript kommen, sind Sie es gewohnt, dass der Zugriff auf einen nicht vorhandenen Schlüssel eine Ausnahme auslöst oder undefined zurückgibt. In Go ist das anders. Hier gibt es keine Ausnahmen, aber einen eigenen eleganten Mechanismus. Und wenn Sie versuchen, einen Wert für einen Schlüssel zu lesen, der nicht existiert, stürzt Go nicht ab, sondern gibt einfach den Nullwert für den Werttyp zurück.
Hört sich praktisch an? Ja, aber es ist auch eine Falle. Wie unterscheidet man die Situation „Schlüssel nicht vorhanden“ von der Situation „Schlüssel vorhanden, aber Wert ist Null“? Genau dafür gibt es eine spezielle Redewendung – das Comma-ok-Idiom. Lassen Sie uns das ein für alle Mal klären.
\n\nWie funktioniert eine Map in Go: Kurze Einführung
\nBevor wir in die Prüfungen eintauchen, erinnern wir uns daran, was eine Map in Go ist. Es ist eine Hashtabelle, die Schlüssel-Wert-Paare speichert. Die Syntax für die Deklaration:
\n// Deklarieren einer Map: Schlüssel sind Strings, Werte sind ganze Zahlen\nvar scores map[string]int\n\n// Initialisieren einer leeren Map (erforderlich!)\nscores = make(map[string]int)\n\n// Oder direkt mit Daten\nscores := map[string]int{\n "Alice": 95,\n "Bob": 87,\n}\nWichtiger Punkt: Wenn Sie versuchen, einen Wert in eine nicht initialisierte Map (nil-Map) zu schreiben, stürzt das Programm mit einer Panik ab. Tun Sie das niemals!
\n\nDie Hauptmethode: Zweiwertige Zuweisung (Comma-ok-Idiom)
\nDies ist die korrekteste und idiomatischste Methode, um zu prüfen, ob ein Schlüssel in einer Map in Go existiert.
\nDie Syntax sieht so aus:
\nvalue, ok := myMap[key]\nHierbei gilt:
\n- \n
value– der Wert, der dem Schlüssel entspricht (oder der Nullwert, wenn der Schlüssel nicht existiert) \n ok– eine boolesche Variable, dietrueist, wenn der Schlüssel existiert, undfalse, wenn nicht \n
Schauen wir uns ein vollständiges Beispiel an:
\npackage main\n\nimport "fmt"\n\nfunc main() {\n // Erstellen einer Map mit Studentennoten\n grades := map[string]int{\n "Maria": 88,\n "Peter": 92,\n "Anna": 0, // Ja, Anna hat 0 Punkte\n }\n\n // Prüfen des Schlüssels "Peter"\n if grade, ok := grades["Peter"]; ok {\n fmt.Printf("Peters Note: %d\\n", grade)\n } else {\n fmt.Println("Peter ist nicht in der Liste")\n }\n\n // Prüfen des Schlüssels "Ivan"\n if grade, ok := grades["Ivan"]; ok {\n fmt.Printf("Ivans Note: %d\\n", grade)\n } else {\n fmt.Println("Ivan ist nicht in der Liste")\n }\n\n // Schwieriger Fall: Schlüssel "Anna" existiert, aber Wert ist 0\n if grade, ok := grades["Anna"]; ok {\n fmt.Printf("Annas Note: %d\\n", grade) // Gibt aus: Annas Note: 0\n }\n}\nBeachten Sie: Für den Schlüssel „Anna“ wird ok true sein, obwohl der Wert Null ist. Deshalb darf man sich nicht nur auf die Wertprüfung verlassen!
Warum kann man nicht einfach mit dem Nullwert vergleichen?
\nViele Anfänger machen diesen Fehler. Sie schreiben so etwas wie:
\nif grades["Ivan"] != 0 {\n fmt.Println("Ivan ist in der Liste!")\n}\nDas ist falsch aus zwei Gründen:
\n- \n
- Für numerische Typen: Wenn Ivan tatsächlich die Note 0 hat, übersehen Sie ihn. \n
- Für andere Typen: Der Nullwert kann ein leerer String (
""),falseodernilsein. Sie können nicht zwischen „Schlüssel nicht vorhanden“ und „Schlüssel vorhanden, aber Wert ist leer“ unterscheiden. \n
Die einzig zuverlässige Methode ist die Verwendung des Comma-ok-Idioms.
\n\nPrüfen eines Schlüssels ohne Werterhalt
\nManchmal müssen Sie nur wissen, ob ein Schlüssel existiert, und der Wert selbst