Übung: Verwenden von Zuordnungen

Abgeschlossen

Eine Zuordnung in Go ist im Grunde eine Hashtabelle, die eine Sammlung von Schlüssel-Wert-Paaren ist. Alle Schlüssel bzw. Werte in einer Zuordnung müssen vom gleichen Typ sein. Sie können jedoch unterschiedliche Typen für Schlüssel und Werte verwenden. Beispielsweise können Schlüssel Zahlen und die Werte Zeichenfolgen sein. Wenn Sie auf ein bestimmtes Element in einer Zuordnung zugreifen möchten, verweisen Sie auf den dazugehörigen Schlüssel.

Deklarieren und Initialisieren einer Zuordnung

Sie müssen das Schlüsselwort map verwenden, um eine Zuordnung zu deklarieren. Dann definieren Sie den Schlüssel- und den Werttyp wie folgt: map[T]T. Wenn Sie beispielsweise eine Zuordnung erstellen möchten, die das Alter von Kursteilnehmern enthält, können Sie den folgenden Code verwenden:

package main

import "fmt"

func main() {
    studentsAge := map[string]int{
        "john": 32,
        "bob":  31,
    }
    fmt.Println(studentsAge)
}

Wenn Sie den vorherigen Code ausführen, wird die folgende Ausgabe angezeigt:

map[bob:31 john:32]

Wenn Sie keine Zuordnung mit Elementen initialisieren möchten, können Sie die integrierte make()-Funktion verwenden, um die Zuordnung im vorherigen Abschnitt zu erstellen. Sie können den folgenden Code verwenden, um eine leere Zuordnung zu erstellen:

studentsAge := make(map[string]int)

Zuordnungen sind dynamisch. Sie können Elemente hinzufügen, darauf zugreifen oder entfernen, nachdem Sie sie erstellt haben. Sehen Sie sich diese Aktionen genauer an.

Elemente hinzufügen

Wenn Sie Elemente hinzufügen möchten, müssen Sie nicht wie bei Slices eine integrierte Funktion verwenden. Zuordnungen sind unkomplizierter. Sie müssen lediglich einen Schlüssel und einen Wert definieren. Wenn das Paar nicht vorhanden ist, wird das Element der Zuordnung hinzugefügt.

Schreiben Sie den Code neu, den Sie zuvor zum Erstellen einer Zuordnung mithilfe der make-Funktion verwendeten haben. Anschließend fügen Sie der Zuordnung Elemente hinzu. Sie können dazu den folgenden Code verwenden:

package main

import "fmt"

func main() {
    studentsAge := make(map[string]int)
    studentsAge["john"] = 32
    studentsAge["bob"] = 31
    fmt.Println(studentsAge)
}

Wenn Sie den Code ausführen, erhalten Sie dieselbe Ausgabe wie zuvor:

map[bob:31 john:32]

Beachten Sie, dass Sie Elemente zu einer Zuordnung hinzugefügt haben, die initialisiert wurde. Wenn Sie jedoch versuchen, dasselbe mit einer nil-Zuordnung auszuführen, wird ein Fehler zurückgegeben. Beispielsweise funktioniert der folgende Code nicht:

package main

import "fmt"

func main() {
    var studentsAge map[string]int
    studentsAge["john"] = 32
    studentsAge["bob"] = 31
    fmt.Println(studentsAge)
}

Wenn Sie den vorherigen Code ausführen, wird der folgende Fehler zurückgegeben:

panic: assignment to entry in nil map

goroutine 1 [running]:
main.main()
        /Users/johndoe/go/src/helloworld/main.go:7 +0x4f
exit status 2

Stellen Sie sicher, dass Sie eine leere Zuordnung (keine nil-Zuordnung) erstellen, indem Sie die make-Funktion wie im vorherigen Codeausschnitt gezeigt verwenden, um Probleme beim Hinzufügen von Elementen zu einer Zuordnung zu vermeiden. Diese Regel gilt nur, wenn Sie Elemente hinzufügen. Wenn Sie Lookup-, Lösch- oder Schleifenvorgänge in einer nil-Zuordnung durchführen, gibt Go keinen panic-Fehler aus. Dieses Verhalten wird in Kürze veranschaulicht.

Zugreifen auf Elemente

Sie verwenden wie bei Arrays oder Slices die gewöhnliche Indexnotation m[key], um auf Elemente in einer Zuordnung zuzugreifen. Im Folgenden finden Sie ein einfaches Beispiel für den Zugriff auf ein Element:

package main

import "fmt"

func main() {
    studentsAge := make(map[string]int)
    studentsAge["john"] = 32
    studentsAge["bob"] = 31
    fmt.Println("Bob's age is", studentsAge["bob"])
}

Wenn Sie die Indexnotation in einer Zuordnung verwenden, erhalten Sie immer eine Antwort, auch wenn der Schlüssel nicht in einer Zuordnung vorhanden ist. Go gibt keinen panic-Fehler aus, wenn Sie auf ein Element zugreifen, das nicht vorhanden ist. Stattdessen wird der Standardwert zurückgegeben. Sie können dieses Verhalten überprüfen, indem Sie den folgenden Code verwenden:

package main

import "fmt"

func main() {
    studentsAge := make(map[string]int)
    studentsAge["john"] = 32
    studentsAge["bob"] = 31
    fmt.Println("Christy's age is", studentsAge["christy"])
}

Wenn Sie den vorherigen Code ausführen, wird die folgende Ausgabe angezeigt:

Christy's age is 0

In vielen Fällen gibt Go keine Fehlermeldung aus, wenn Sie auf ein Element zugreifen, das in einer Zuordnung nicht vorhanden ist. Manchmal müssen Sie jedoch wissen, ob ein Element vorhanden ist oder nicht. In Go kann die Indexnotation für eine Zuordnung zwei Werte liefern. Der erste ist der Wert eines Elements. Die zweite ist ein boolesches Flag, das angibt, ob der Schlüssel vorhanden ist.

Sie können den folgenden Code ausführen, um das Problem im Zusammenhang mit dem letzten Codeschnipsel zu beheben:

package main

import "fmt"

func main() {
    studentsAge := make(map[string]int)
    studentsAge["john"] = 32
    studentsAge["bob"] = 31

    age, exist := studentsAge["christy"]
    if exist {
        fmt.Println("Christy's age is", age)
    } else {
        fmt.Println("Christy's age couldn't be found")
    }
}

Wenn Sie den vorherigen Code ausführen, wird die folgende Ausgabe angezeigt:

Christy's age couldn't be found

Verwenden Sie den zweiten Codeausschnitt, um zu prüfen, ob ein Schlüssel in einer Zuordnung vorhanden ist, bevor Sie darauf zugreifen.

Entfernen von Elementen

Verwenden Sie die integrierte delete()-Funktion, um ein Element aus einer Zuordnung zu entfernen. Im Folgenden finden Sie ein Beispiel für das Entfernen von Elementen aus einer Zuordnung:

package main

import "fmt"

func main() {
    studentsAge := make(map[string]int)
    studentsAge["john"] = 32
    studentsAge["bob"] = 31
    delete(studentsAge, "john")
    fmt.Println(studentsAge)
}

Wenn Sie den Code ausführen, erhalten Sie die folgende Ausgabe:

map[bob:31]

Wie bereits erwähnt gibt Go keinen panic-Fehler aus, wenn Sie versuchen, ein nicht vorhandenes Element zu löschen. Hier finden Sie ein Beispiel für dieses Verhalten:

package main

import "fmt"

func main() {
    studentsAge := make(map[string]int)
    studentsAge["john"] = 32
    studentsAge["bob"] = 31
    delete(studentsAge, "christy")
    fmt.Println(studentsAge)
}

Wenn Sie den Code ausführen, wird keine Fehlermeldung angezeigt, und Sie erhalten die folgende Ausgabe:

map[bob:31 john:32]

Schleife in einer Zuordnung

Abschließend sehen Sie sich an, wie Sie eine Schleife in einer Zuordnung durchlaufen können, um programmgesteuert auf alle Elemente zuzugreifen. Zu diesem Zweck können Sie wie im folgenden Beispiel gezeigt die bereichsbasierte Schleife verwenden:

package main

import (
    "fmt"
)

func main() {
    studentsAge := make(map[string]int)
    studentsAge["john"] = 32
    studentsAge["bob"] = 31
    for name, age := range studentsAge {
        fmt.Printf("%s\t%d\n", name, age)
    }
}

Wenn Sie den vorherigen Code ausführen, wird die folgende Ausgabe angezeigt:

john    32
bob     31

Beachten Sie, wie Sie die Informationen zum Schlüssel und dem Wert in verschiedenen Variablen speichern können. In diesem Fall speichern Sie den Schlüssel in der Variable name und den Wert in der Variable age. Daher gibt range zuerst den Schlüssel und dann den Wert dieses Elements aus. Sie können eines dieser beiden Elemente ignorieren, indem Sie wie im folgenden Beispiel gezeigt die Variable _ verwenden:

package main

import (
    "fmt"
)

func main() {
    studentsAge := make(map[string]int)
    studentsAge["john"] = 32
    studentsAge["bob"] = 31

    for _, age := range studentsAge {
        fmt.Printf("Ages %d\n", age)
    }
}

Obwohl es in diesem Fall nicht sinnvoll ist, das Alter auf diese Weise auszugeben, gibt es Fälle, in denen Sie den Schlüssel eines Elements nicht kennen müssen. Alternativ können Sie wie in diesem Beispiel nur den Schlüssel des Elements verwenden:

package main

import (
    "fmt"
)

func main() {
    studentsAge := make(map[string]int)
    studentsAge["john"] = 32
    studentsAge["bob"] = 31

    for name := range studentsAge {
        fmt.Printf("Names %s\n", name)
    }
}