Grundlagen von Go-Wörterbüchern (Maps)

GolangGolangBeginner
Jetzt üben

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

Herzlich willkommen, Gophers, in diesem neuen Kapitel.

In diesem Kapitel werden wir die Grundlagen der Verwendung von Maps (Karten) in Go kennenlernen und die Rolle von nil in Go analysieren.

Nach Abschluss dieses Kapitels können Sie Maps in Ihren täglichen Entwicklungsaufgaben einsetzen.

Wissenspunkte:

  • Deklarieren einer Map
  • Initialisieren einer Map
  • Hinzufügen, Löschen, Aktualisieren und Suchen von Map-Elementen
  • Prüfen, ob ein Map-Element existiert
  • Iterieren über eine Map

Einführung in Wörterbücher (Dictionaries)

Also, was ist ein Wörterbuch (Dictionary)?

In der Informatik ist ein Wörterbuch (Dictionary) eine spezielle Datenstruktur, die aus Schlüssel-Wert-Paaren besteht.

Schlüssel-Wert-Paar: Ein Paar von Elementen, wobei das eine Element der Schlüssel und das andere der Wert genannt wird.

Warum sollten wir also ein Wörterbuch (Dictionary) verwenden?

Da Wörterbücher (Dictionaries) bei Operationen wie dem Hinzufügen, Löschen, Aktualisieren und Suchen von Elementen sehr effizient sind, glaube ich, dass Sie alle diese Datenstruktur sehr nützlich finden werden.

Bildbeschreibung

Deklaration von Maps

Bei einer neuen Datenstruktur ist der erste Schritt, zu lernen, wie man sie deklariert.

Für eine map ist die Art und Weise, sie zu definieren, wie folgt:

var variableName map[keyType]valueType

Beispiel:

var a map[string]int

Da eine map jedoch ein Referenztyp ist, wird es bei einer Deklaration wie im obigen Code zu einem Problem kommen.

Erstellen Sie eine Datei map.go im Verzeichnis ~/project:

touch ~/project/map.go

Schreiben Sie folgenden Code in die Datei map.go:

package main

func main() {
    // Declare a map named m with key type as string and value type as int
    var m map[string]int
    // Add a data entry "labex"->1 to it
    m["labex"] = 1 // Program crashes
}

Führen Sie das Programm aus:

go run map.go

Wir stellen fest, dass das Programm abstürzt und einen Fehler ausgibt:

panic: assignment to entry in nil map

Das bedeutet, dass das Zuweisen eines Elements zu einer nil map ein fehlerhaftes Verhalten ist.

Das liegt daran, dass Datenstrukturen wie Slices, Maps, Kanäle und Zeiger vor der Verwendung initialisiert werden müssen.

Und nil ist der initiale Standardwert für eine Map, was bedeutet, dass bei der Definition kein Speicher für die Variable zugewiesen wird.

Der Anfangswert nil

Im vorherigen Abschnitt haben wir erwähnt, dass es ein fehlerhaftes Verhalten ist, ein Element einer nil-Map zuzuweisen.

Wir nutzen diese Gelegenheit, um die wahre Bedeutung von nil in Go zu erkunden.

Das Wesen von nil ist ein vordeklarierter Bezeichner.

Für grundlegende Datentypen sind ihre Anfangswerte unterschiedlich:

  • Boolesche Werte
  • Numerische Werte
  • Strings

Für Slices, Wörterbücher (Dictionaries), Zeiger, Kanäle und Funktionen ist ihr Anfangswert jedoch nil. Es ist nicht der uns bekannte Standardanfangswert.

Dies zeigt sich bei den Instanzierungsobjekten, denen nil zugewiesen wird. Obwohl sie ausgegeben werden können, können sie nicht verwendet werden.

Darüber hinaus gibt es einige Punkte zu beachten, wenn es um nil geht.

Nichtvergleichbarkeit verschiedener Typen von nil

package main

import "fmt"

func main() {
    var m map[int]string
    var p *int
    fmt.Printf("%v", m == p)
}

Die Programmausgabe lautet wie folgt:

invalid operation: m == p (mismatched types map[int]string and *int)

Das heißt, wir können das nil eines Zeigers vom Typ int nicht mit dem nil einer Map vergleichen.

Sie sind nicht vergleichbar.

nil ist kein Schlüsselwort

package main

import "fmt"

func main() {
    var nilValue = "= =$"
    fmt.Println(nilValue)
}

Die Programmausgabe lautet wie folgt:

= =$

Wir können eine Variable mit dem Namen nil definieren, und sie kann fehlerfrei kompiliert werden. Wir empfehlen Ihnen jedoch dringend, dies in der praktischen Entwicklung nicht zu tun.

Nichtvergleichbarkeit von nil

package main

import "fmt"

func main() {
    fmt.Println(nil == nil)
}

Die Programmausgabe lautet wie folgt:

invalid operation: nil == nil (operator == not defined on nil)

Deklaration mit dem Schlüsselwort make

Nachdem wir die Bedeutung von nil verstanden haben, lösen wir nun das Problem der Speicherzuweisung für Wörterbücher (Dictionaries).

Hier verwenden wir das Schlüsselwort make, um Speicher zuzuweisen.

Die make-Funktion erzeugt einen Wert eines angegebenen Typs, der bereits initialisiert ist, und gibt ihn als Rückgabewert zurück.

package main

import "fmt"

func main() {
    var m map[string]int     // Declare a dictionary
    m = make(map[string]int) // Allocate memory to the dictionary
    m["labex"] = 1       // Add data to the dictionary
    fmt.Println(m)
}

Die Programmausgabe lautet wie folgt:

map[labex:1]

Der obige Code zeigt, wie man einem deklarierten Wörterbuch (Dictionary) mithilfe des Schlüsselworts make Speicher zuweist.

Wir können diesen Prozess auch vereinfachen:

Schreiben Sie folgenden Code in die Datei map.go:

package main

import "fmt"

func main() {
    m := make(map[string]int) // Declare and initialize a dictionary
    m["labex"] = 666      // Add data to the dictionary
    fmt.Println(m)
}

Die Ausgabe des Programms lautet wie folgt:

map[labex:666]

Der obige Code zeigt, wie man ein Wörterbuch (Dictionary) mit dem Schlüsselwort make deklariert.

Manuelle Initialisierung einer leeren Map

Im vorherigen Abschnitt haben wir gezeigt, wie man das Schlüsselwort make verwendet, um eine Map zu initialisieren. Jetzt wollen wir uns eine andere Methode ansehen: die manuelle Initialisierung einer leeren Map mithilfe der Literalsyntax.

Diese Methode ist kompakt und ermöglicht es Ihnen, eine leere Map zu erstellen, die sofort einsatzbereit ist, ohne dass Sie explizit Speicher zuweisen müssen.

Schreiben Sie folgenden Code in die Datei map.go:

package main

import "fmt"

func main() {
    // Using literal syntax to initialize an empty map
    m := map[string]int{}

    // Adding elements to the map
    m["labex"] = 777
    m["labs"] = 11

    fmt.Println(m) // Output the map with added elements
}

Die Syntax map[keyType]valueType{} erstellt eine leere, einsatzbereite Map. Sobald die Map initialisiert ist, können Sie ihr Elemente mithilfe der Syntax map[key] = value hinzufügen.

Wenn Sie den obigen Code ausführen, wird das Programm folgendes ausgeben:

map[labex:777 labs:11]

Vorteile der manuellen Initialisierung:

  • Bietet eine schnelle Möglichkeit, eine leere Map zu erstellen, ohne das Schlüsselwort make zu verwenden.
  • Nützlich, wenn Sie mit einer leeren Map beginnen und diese dynamisch befüllen müssen.

Echte Initialisierung des Wörterbuchs (Dictionaries)

Da wir ein leeres Wörterbuch (Dictionary) initialisieren können, können wir es auch mit einigen Anfangswerten versehen.

Schreiben Sie folgenden Code in die Datei map.go:

package main

import "fmt"

func main() {
    m := map[string]int{
        "labex": 777,
        "labs": 11,
    }
    m["labby"] = 666
    fmt.Println(m)
}

Die Programmausgabe lautet wie folgt:

map[labby:666 labs:11 labex:777]

Beachten Sie, dass beim Initialisieren eines Wörterbuchs (Dictionaries) in Go nach jedem Element, einschließlich des letzten, ein Komma hinzugefügt werden muss.

Hinzufügen und Aktualisieren von Wörterbuchelementen (Dictionary-Elementen)

Das Hinzufügen von Elementen zu einem Wörterbuch (Dictionary) ist sehr einfach, wie das obige Codebeispiel gezeigt hat.

Die Syntax lautet:

dictionaryInstance[keyToAdd] = valueToAdd

Beispiel:

m := map[string]int{}
m["labby"] = 666

Hinweis: In Go muss jeder key in einer map eindeutig sein.

Schreiben Sie folgenden Code in die Datei map.go:

package main

import "fmt"

func main() {
    m := map[string]int{}
    m["labby"] = 666
    m["labby"] = 777
    fmt.Println(m)
}

Die Programmausgabe lautet wie folgt:

map[labby:777]

Wir haben festgestellt, dass der ausgegebene Wert auf 777 geändert wurde. Das heißt, wenn wir unterschiedliche Werte für denselben key schreiben, wird der entsprechende value auf den neuen Wert aktualisiert.

So aktualisieren oder ändern wir ein Wörterbuch (Dictionary).

Löschen von Wörterbuchelementen (Dictionary-Elementen)

Wie können wir ein Element aus einem Wörterbuch (Dictionary) löschen?

Wir müssen die integrierte delete-Funktion verwenden.

Schreiben Sie folgenden Code in die Datei map.go:

package main

import "fmt"

func main() {
    m := map[string]int{
        "labex": 777,
        "labs": 11,
        "labby": 666,
    }
    fmt.Println(m)
    delete(m, "labs")
    fmt.Println(m)
}

Die Programmausgabe lautet wie folgt:

map[labby:666 labs:11 labex:777]
map[labby:666 labex:777]

Die delete-Funktion nimmt zwei Argumente entgegen. Das erste Argument ist das Wörterbuch (Dictionary), auf das die Operation angewendet werden soll, und das zweite Argument ist der Schlüssel (key), der gelöscht werden soll.

Natürlich hat die delete-Funktion auch andere Anwendungen, aber in diesem Lab besprechen wir nur ihre Verwendung in Wörterbüchern (Dictionaries).

Suchen nach Wörterbuchelementen (Dictionary-Elementen)

Was passiert, wenn wir in einem Wörterbuch (Dictionary) nach einem Element suchen, das nicht existiert?

package main

import "fmt"

func main() {
    m := map[string]int{
        "labex": 0,
    }
    fmt.Print("The value of labs is: ")
    fmt.Println(m["labs"])
}

Die Programmausgabe lautet wie folgt:

The value of labs is: 0

Wir haben festgestellt, dass wenn das Element im Wörterbuch (Dictionary) nicht existiert, die Abfrage den Standardwert des Wertetyps zurückgibt.

Was ist mit dem Schlüssel (key) im Wörterbuch, dessen Wert 0 ist?

package main

import "fmt"

func main() {
    m := map[string]int{
        "labex": 0,
    }
    fmt.Print("The value of labs is: ")
    fmt.Println(m["labs"])
    fmt.Print("The value of labex is: ")
    fmt.Println(m["labex"])
}

Die Programmausgabe lautet wie folgt:

The value of labs is: 0
The value of labex is: 0

Wir haben festgestellt, dass für ein Wörterbuch (Dictionary) die Darstellung eines nicht existierenden Werts und eines existierenden Werts mit Standardwert gleich ist.

Dies bringt uns in große Verwirrung. Wie können wir das Problem lösen?

Es stellt sich heraus, dass die Entwickler von Go bereits an dieses Problem gedacht haben. Wenn wir ein Element in einem Wörterbuch (Dictionary) abfragen, gibt es ein oder zwei Variablen als Rückgabewerte.

Das heißt:

labs, ok := m["labs"]

Ändern Sie die Datei map.go wie folgt:

package main

import "fmt"

func main() {
    m := map[string]int{
        "labex": 0,
    }
    labs, ok := m["labs"]
    fmt.Print("The value of labs is: ")
    fmt.Print(labs)
    fmt.Print(" Does it exist? ")
    fmt.Println(ok)
    labex, ok2 := m["labex"]
    fmt.Print("The value of labex is: ")
    fmt.Print(labex)
    fmt.Print(" Does it exist? ")
    fmt.Println(ok2)
}

Die Programmausgabe lautet wie folgt:

The value of labs is: 0 Does it exist? false
The value of labex is: 0 Does it exist? true

Jetzt können wir den zweiten Rückgabewert der Abfrage verwenden, um zu bestimmen, ob das zurückgegebene Ergebnis ein existierender Standardwert oder ein nicht existierender Standardwert ist.

Iterieren über Wörterbücher (Dictionaries)

In bestimmten Szenarien müssen wir über ein gesamtes Wörterbuch (Dictionary) iterieren, jedes Schlüssel-Wert-Paar (key-value pair) abfragen und verarbeiten. Wie können wir dies erreichen?

package main

import (
    "fmt"
)

func main() {
    m := map[string]int{
        "labex": 777,
        "labs":   11,
        "labby":     666,
    }
    for key, value := range m {
        fmt.Println(key, value)
    }
}

Die Programmausgabe lautet wie folgt:

labby 666
labs 11
labex 777

Aus der Ausgabe können wir sehen, dass die Art und Weise, wie man über ein Wörterbuch (Dictionary) iteriert, der Iteration über Slices oder Arrays sehr ähnlich ist.

Zusammenfassung

In diesem Lab haben wir die grundlegende Verwendung von Wörterbüchern (Dictionaries) gelernt, einschließlich:

  • Die Deklaration von Wörterbüchern (Dictionaries) und wie man das Deklarationsproblem löst
  • Die Eigenschaften des Initialwerts nil
  • Die Methoden zur Initialisierung von Wörterbüchern (Dictionaries)
  • Das Hinzufügen, Entfernen, Aktualisieren und Suchen von Elementen in Wörterbüchern (Dictionaries)
  • Das Erkennen der Existenz von Wörterbuchelementen (Dictionary-Elementen)
  • Das Iterieren über Wörterbücher (Dictionaries)