Grundlegendes zu Maps in Go

Die meisten modernen Programmiersprachen haben das Konzept einesdictionary- oder eineshash-Typs. Diese Typen werden üblicherweise verwendet, um Daten paarweise mit einemkey zu speichern, der einemvalue zugeordnet ist.

In Go ist der Datentypmapder Typ, den die meisten Programmierer alsdictionarybetrachten würden. Es ordnet Schlüssel Werten zu und bildet Schlüssel-Wert-Paare, die eine nützliche Methode zum Speichern von Daten in Go darstellen. Eine Karte wird unter Verwendung des Schlüsselwortsmap gefolgt vom Schlüsseldatentyp in eckigen Klammern[ ] gefolgt vom Wertdatentyp erstellt. Die Schlüssel-Wert-Paare werden dann in geschweifte Klammern auf beiden Seiten gesetzt. \ {}:

map[key]value{}

Normalerweise verwenden Sie Karten in Go, um verwandte Daten zu speichern, z. B. die in einer ID enthaltenen Informationen. Eine Karte mit Daten sieht folgendermaßen aus:

map[string]string{"name": "Sammy", "animal": "shark", "color": "blue", "location": "ocean"}

Zusätzlich zu den geschweiften Klammern gibt es auf der Karte Doppelpunkte, die die Schlüssel-Wert-Paare verbinden. Die Wörter links von den Doppelpunkten sind die Schlüssel. Schlüssel können beliebigecomparable-Typen in Go sein, z. B.strings,ints usw.

Die Schlüssel in der Beispielkarte sind:

  • "name"

  • "animal"

  • "color"

  • "location"

Die Wörter rechts von den Doppelpunkten sind die Werte. Werte können beliebige Datentypen sein. Die Werte in der Beispielkarte sind:

  • "Sammy"

  • "shark"

  • "blue"

  • "ocean"

Wie bei den anderen Datentypen können Sie die Karte in einer Variablen speichern und ausdrucken:

sammy := map[string]string{"name": "Sammy", "animal": "shark", "color": "blue", "location": "ocean"}
fmt.Println(sammy)

Dies wäre Ihre Ausgabe:

Outputmap[animal:shark color:blue location:ocean name:Sammy]

Die Reihenfolge der Schlüssel-Wert-Paare hat sich möglicherweise verschoben. In Go ist der Kartendatentyp ungeordnet. Unabhängig von der Reihenfolge bleiben die Schlüssel-Wert-Paare erhalten, sodass Sie auf Daten zugreifen können, die auf ihrer relationalen Bedeutung basieren.

Zugriff auf Kartenelemente

Sie können die Werte einer Karte aufrufen, indem Sie auf die zugehörigen Schlüssel verweisen. Da Karten Schlüssel-Wert-Paare zum Speichern von Daten bieten, können sie wichtige und nützliche Elemente in Ihrem Go-Programm sein.

Wenn Sie Sammys Benutzernamen isolieren möchten, können Sie dies tun, indem Siesammy["name"] aufrufen. Die Variable mit Ihrer Karte und dem zugehörigen Schlüssel. Drucken wir das aus:

fmt.Println(sammy["name"])

Und erhalte den Wert als Ausgabe:

OutputSammy

Karten verhalten sich wie eine Datenbank. Anstatt wie bei einem Slice eine Ganzzahl aufzurufen, um einen bestimmten Indexwert abzurufen, weisen Sie einem Schlüssel einen Wert zu und rufen diesen Schlüssel auf, um den zugehörigen Wert abzurufen.

Durch Aufrufen des Schlüssels"name" erhalten Sie den Wert dieses Schlüssels, nämlich"Sammy".

Ebenso können Sie die verbleibenden Werte in dersammy-Karte im selben Format aufrufen:

fmt.Println(sammy["animal"])
// returns shark

fmt.Println(sammy["color"])
// returns blue

fmt.Println(sammy["location"])
// returns ocean

Indem Sie die Schlüssel-Wert-Paare in Kartendatentypen verwenden, können Sie auf Schlüssel verweisen, um Werte abzurufen.

Schlüssel und Werte

Im Gegensatz zu einigen Programmiersprachen verfügt Go über keineconvenience-Funktionen zum Auflisten der Schlüssel oder Werte einer Karte. Ein Beispiel hierfür wäre Pythons.keys()-Methode für Wörterbücher. Es ermöglicht jedoch eine Iteration mit dem Operatorrange:

for key, value := range sammy {
    fmt.Printf("%q is the key for the value %q\n", key, value)
}

Beim Durchlaufen einer Karte in Go werden zwei Werte zurückgegeben. Der erste Wert ist der Schlüssel und der zweite Wert ist der Wert. Go erstellt diese Variablen mit dem richtigen Datentyp. In diesem Fall war der Kartenschlüsselstring, sodasskey auch eine Zeichenfolge ist. Dasvalue ist auch eine Zeichenfolge:

Output"animal" is the key for the value "shark"
"color" is the key for the value "blue"
"location" is the key for the value "ocean"
"name" is the key for the value "Sammy"

Um nur eine Liste der Schlüssel zu erhalten, können Sie den Bereichsoperator erneut verwenden. Sie können nur eine Variable deklarieren, um nur auf die Schlüssel zuzugreifen:

keys := []string{}

for key := range sammy {
    keys = append(keys, key)
}
fmt.Printf("%q", keys)

Das Programm beginnt mit der Deklaration eines Slice, in dem Ihre Schlüssel gespeichert werden sollen.

In der Ausgabe werden nur die Schlüssel Ihrer Karte angezeigt:

Output["color" "location" "name" "animal"]

Auch hier werden die Schlüssel nicht sortiert. Wenn Sie sie sortieren möchten, verwenden Sie die Funktionsort.Strings aus dem Paketsort:

sort.Strings(keys)

Mit dieser Funktion erhalten Sie folgende Ausgabe:

Output["animal" "color" "location" "name"]

Sie können dasselbe Muster verwenden, um nur die Werte in einer Karte abzurufen. Im nächsten Beispiel ordnen Sie das Segment vorab zu, um Zuordnungen zu vermeiden, wodurch das Programm effizienter wird:

sammy := map[string]string{"name": "Sammy", "animal": "shark", "color": "blue", "location": "ocean"}

items := make([]string, len(sammy))

var i int

for _, v := range sammy {
    items[i] = v
    i++
}
fmt.Printf("%q", items)

Zuerst deklarieren Sie einen Slice, in dem Ihre Schlüssel gespeichert werden sollen. Da Sie wissen, wie viele Elemente Sie benötigen, können Sie potenzielle Speicherzuordnungen vermeiden, indem Sie das Segment mit genau derselben Größe definieren. Anschließend deklarieren Sie Ihre Indexvariable. Da Sie den Schlüssel nicht möchten, verwenden Sie beim Starten Ihrer Schleife den Operator_, um den Wert des Schlüssels zu ignorieren. Ihre Ausgabe wäre die folgende:

Output["ocean" "Sammy" "shark" "blue"]

Um die Anzahl der Elemente in einer Karte zu bestimmen, können Sie die integrierte Funktionlenverwenden:

sammy := map[string]string{"name": "Sammy", "animal": "shark", "color": "blue", "location": "ocean"}
fmt.Println(len(sammy))

In der Ausgabe wird die Anzahl der Elemente in Ihrer Karte angezeigt:

Output4

Obwohl Go nicht mit praktischen Funktionen zum Abrufen von Schlüsseln und Werten ausgestattet ist, sind nur wenige Codezeilen erforderlich, um die Schlüssel und Werte bei Bedarf abzurufen.

Existenz überprüfen

Maps in Go gibt den Nullwert für den Wertetyp der Map zurück, wenn der angeforderte Schlüssel fehlt. Aus diesem Grund benötigen Sie eine alternative Methode, um eine gespeicherte Null gegenüber einem fehlenden Schlüssel zu unterscheiden.

Sehen wir uns einen Wert in einer Map an, von dem Sie wissen, dass er nicht existiert, und schauen wir uns den zurückgegebenen Wert an:

counts := map[string]int{}
fmt.Println(counts["sammy"])

Sie sehen die folgende Ausgabe:

Output0

Obwohl der Schlüsselsammy nicht in der Karte enthalten war, gab Go dennoch den Wert0 zurück. Dies liegt daran, dass der Wertdatentypint ist und dass Go für alle Variablen einen Nullwert hat und den Nullwert von0 zurückgibt.

In vielen Fällen ist dies unerwünscht und würde zu einem Programmfehler führen. Wenn Sie den Wert in einer Karte nachschlagen, kann Go einen zweitenoptional-Wert zurückgeben. Dieser zweite Wert istbool und isttrue, wenn der Schlüssel gefunden wurde, oderfalse, wenn der Schlüssel nicht gefunden wurde. In Go wird dies alsok-Sprache bezeichnet. Obwohl Sie die Variable, die das zweite Argument erfasst, beliebig benennen können, nennen Sie sie in Go immerok:

count, ok := counts["sammy"]

Wenn der Schlüsselsammy in der Kartecounts vorhanden ist, istoktrue. Andernfalls istok falsch.

Mit der Variablenokkönnen Sie entscheiden, was in Ihrem Programm geschehen soll:

if ok {
    fmt.Printf("Sammy has a count of %d\n", count)
} else {
    fmt.Println("Sammy was not found")
}

Dies würde zu folgender Ausgabe führen:

OutputSammy was not found

In Go können Sie Variablendeklaration und bedingte Prüfung mit einem if / else-Block kombinieren. Auf diese Weise können Sie eine einzelne Anweisung für diese Prüfung verwenden:

if count, ok := counts["sammy"]; ok {
    fmt.Printf("Sammy has a count of %d\n", count)
} else {
    fmt.Println("Sammy was not found")
}

Wenn Sie einen Wert aus einer Map in Go abrufen, ist es immer ratsam, zu überprüfen, ob er vorhanden ist, um Fehler in Ihrem Programm zu vermeiden.

Karten ändern

Karten sind eine veränderbare Datenstruktur, sodass Sie sie ändern können. Sehen wir uns in diesem Abschnitt das Hinzufügen und Löschen von Kartenelementen an.

Hinzufügen und Ändern von Kartenelementen

Ohne Verwendung einer Methode oder Funktion können Sie Zuordnungen Schlüssel-Wert-Paare hinzufügen. Verwenden Sie dazu den Namen der Kartenvariablen, gefolgt vom Schlüsselwert in eckigen Klammern[ ], und verwenden Sie den Operator gleich=, um einen neuen Wert festzulegen:

map[key] = value

In der Praxis können Sie diese Arbeit sehen, indem Sie einer Karte mit dem Namenusernames ein Schlüssel-Wert-Paar hinzufügen:

usernames := map[string]string{"Sammy": "sammy-shark", "Jamie": "mantisshrimp54"}

usernames["Drew"] = "squidly"
fmt.Println(usernames)

Die Ausgabe zeigt das Schlüssel-Wert-Paar des neuenDrew:squidlyin der Karte an:

Outputmap[Drew:squidly Jamie:mantisshrimp54 Sammy:sammy-shark]

Da Karten ungeordnet zurückgegeben werden, kann dieses Paar an einer beliebigen Stelle in der Kartenausgabe auftreten. Wenn Sie die Zuordnung vonusernamespäter in Ihrer Programmdatei verwenden, enthält sie das zusätzliche Schlüssel-Wert-Paar.

Sie können diese Syntax auch zum Ändern des einem Schlüssel zugewiesenen Werts verwenden. In diesem Fall verweisen Sie auf einen vorhandenen Schlüssel und übergeben ihm einen anderen Wert.

Stellen Sie sich eine Karte mit dem Namenfollowers vor, die Follower von Benutzern in einem bestimmten Netzwerk verfolgt. Der Benutzer"drew" hatte heute einen Anstieg der Follower, daher müssen Sie den an den Schlüssel"drew" übergebenen ganzzahligen Wert aktualisieren. Mit der FunktionPrintln()überprüfen Sie, ob die Karte geändert wurde:

followers := map[string]int{"drew": 305, "mary": 428, "cindy": 918}
followers["drew"] = 342
fmt.Println(followers)

Ihre Ausgabe zeigt den aktualisierten Wert fürdrew:

Outputmap[cindy:918 drew:342 mary:428]

Sie sehen, dass die Anzahl der Follower vom ganzzahligen Wert von305 auf342 gestiegen ist.

Mit dieser Methode können Sie Karten mit Benutzereingaben Schlüssel-Wert-Paare hinzufügen. Schreiben wir ein schnelles Programm namensusernames.go, das in der Befehlszeile ausgeführt wird und es dem Benutzer ermöglicht, weitere Namen und zugehörige Benutzernamen hinzuzufügen:

usernames.go

package main

import (
    "fmt"
    "strings"
)

func main() {
    usernames := map[string]string{"Sammy": "sammy-shark", "Jamie": "mantisshrimp54"}

    for {
        fmt.Println("Enter a name:")

        var name string
        _, err := fmt.Scanln(&name)

        if err != nil {
            panic(err)
        }

        name = strings.TrimSpace(name)

        if u, ok := usernames[name]; ok {
            fmt.Printf("%q is the username of %q\n", u, name)
            continue
        }

        fmt.Printf("I don't have %v's username, what is it?\n", name)

        var username string
        _, err = fmt.Scanln(&username)

        if err != nil {
            panic(err)
        }

        username = strings.TrimSpace(username)

        usernames[name] = username

        fmt.Println("Data updated.")
    }
}

Inusernames.go definieren Sie zuerst die ursprüngliche Karte. Anschließend richten Sie eine Schleife ein, um die Namen zu durchlaufen. Sie fordern Ihren Benutzer auf, einen Namen einzugeben und eine Variable zu deklarieren, in der er gespeichert werden soll. Als nächstes überprüfen Sie, ob Sie einen Fehler hatten. In diesem Fall wird das Programm mitpanic beendet. DaScanln die gesamte Eingabe einschließlich des Wagenrücklaufs erfasst, müssen Sie Leerzeichen aus der Eingabe entfernen. Sie tun dies mit der Funktionstrings.TrimSpace.

Derif-Block prüft, ob der Name in der Karte vorhanden ist, und gibt Feedback aus. Wenn der Name vorhanden ist, kehrt er zum Anfang der Schleife zurück. Befindet sich der Name nicht in der Karte, gibt er dem Benutzer eine Rückmeldung und fordert dann einen neuen Benutzernamen für den zugeordneten Namen an. Das Programm prüft erneut, ob ein Fehler vorliegt. Ohne Fehler wird der Wagenrücklauf abgeschnitten, dem Namenstaste der Benutzername zugewiesen und anschließend die Rückmeldung gedruckt, dass die Daten aktualisiert wurden.

Führen Sie das Programm in der Befehlszeile aus:

go run usernames.go

Sie sehen die folgende Ausgabe:

OutputEnter a name:
Sammy
"sammy-shark" is the username of "Sammy"
Enter a name:
Jesse
I don't have Jesse's username, what is it?
JOctopus
Data updated.
Enter a name:

Wenn Sie mit dem Testen fertig sind, drücken SieCTRL + C, um das Programm zu verlassen.

Dies zeigt, wie Sie Karten interaktiv ändern können. Bei diesem speziellen Programm gehen alle Daten verloren, sobald Sie das Programm mitCTRL + C beenden, es sei denn, Sie implementieren eine Methode zum Lesen und Schreiben von Dateien.

Zusammenfassend können Sie Maps Elemente hinzufügen oder Werte mit der Syntaxmap[key] = valueändern.

Kartenelemente löschen

So wie Sie Schlüssel-Wert-Paare hinzufügen und Werte innerhalb des Kartendatentyps ändern können, können Sie auch Elemente innerhalb einer Karte löschen.

Um ein Schlüssel-Wert-Paar aus einer Karte zu entfernen, können Sie die integrierte Funktiondelete() verwenden. Das erste Argument ist die Karte, aus der Sie löschen. Das zweite Argument ist der Schlüssel, den Sie löschen:

delete(map, key)

Definieren wir eine Karte mit Berechtigungen:

permissions := map[int]string{1: "read", 2: "write", 4: "delete", 8: "create", 16:"modify"}

Sie benötigen die Berechtigungmodifynicht mehr, sodass Sie sie von Ihrer Karte entfernen. Anschließend drucken Sie die Karte aus, um zu bestätigen, dass sie entfernt wurde:

permissions := map[int]string{1: "read", 2: "write", 4: "delete", 8: "create", 16: "modify"}
delete(permissions, 16)
fmt.Println(permissions)

Die Ausgabe bestätigt das Löschen:

Outputmap[1:read 2:write 4:delete 8:create]

Die Zeiledelete(permissions, 16) entfernt das Schlüssel-Wert-Paar16:"modify" aus der Karte vonpermissions.

Wenn Sie eine Karte von allen Werten löschen möchten, können Sie dies tun, indem Sie sie gleich einer leeren Karte desselben Typs setzen. Dadurch wird eine neue leere Karte erstellt und die alte Karte wird vom Garbage Collector aus dem Speicher gelöscht.

Entfernen wir alle Elemente in der Karte vonpermissions:

permissions = map[int]string{}
fmt.Println(permissions)

Die Ausgabe zeigt, dass Sie jetzt eine leere Karte ohne Schlüssel-Wert-Paare haben:

Outputmap[]

Da es sich bei Karten um veränderbare Datentypen handelt, können sie hinzugefügt, geändert sowie Elemente entfernt und gelöscht werden.

Fazit

In diesem Tutorial wurde die Kartendatenstruktur in Go untersucht. Maps bestehen aus Schlüssel-Wert-Paaren und bieten die Möglichkeit, Daten zu speichern, ohne auf die Indizierung angewiesen zu sein. Auf diese Weise können wir Werte basierend auf ihrer Bedeutung und Beziehung zu anderen Datentypen abrufen.