Oefening: kaarten gebruiken

Voltooid

Een kaart in Go is in feite een hash-tabel, een verzameling sleutel- en waardeparen. Alle sleutels in een kaart moeten van hetzelfde type zijn en dus ook de waarden. U kunt echter verschillende typen gebruiken voor sleutels en waarden. Sleutels kunnen bijvoorbeeld getallen zijn en de waarden kunnen tekenreeksen zijn. Als u toegang wilt krijgen tot een bepaald item in een kaart, verwijst u naar de sleutel.

Een kaart declareren en initialiseren

Als u een kaart wilt declareren, moet u het map trefwoord gebruiken. Vervolgens definieert u het sleutel- en waardetype, zoals hieronder: map[T]T. Als u bijvoorbeeld een kaart wilt maken die de leeftijd van leerlingen/studenten bevat, kunt u de volgende code gebruiken:

package main

import "fmt"

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

Wanneer u de voorgaande code uitvoert, ziet u de volgende uitvoer:

map[bob:31 john:32]

Als u een kaart niet wilt initialiseren met items, kunt u de ingebouwde make() functie gebruiken om de kaart in de vorige sectie te maken. U kunt de volgende code gebruiken om een lege kaart te maken:

studentsAge := make(map[string]int)

Kaarten zijn dynamisch. U kunt items toevoegen, openen of verwijderen nadat u ze hebt gemaakt. Laten we die acties eens bekijken.

Items toevoegen

Als u items wilt toevoegen, hoeft u geen ingebouwde functie te gebruiken, zoals bij segmenten. Kaarten zijn eenvoudiger. U hoeft alleen een sleutel en een waarde te definiëren. Als het paar niet bestaat, wordt het item toegevoegd aan de kaart.

Laten we de code die we eerder hebben gebruikt voor het maken van een kaart opnieuw schrijven met behulp van de make functie. Vervolgens voegen we items toe aan de kaart. U kunt de volgende code gebruiken:

package main

import "fmt"

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

Wanneer u de code uitvoert, krijgt u dezelfde uitvoer als voorheen:

map[bob:31 john:32]

U ziet dat we items hebben toegevoegd aan een kaart die is geïnitialiseerd. Maar als u hetzelfde probeert te doen met een nil kaart, krijgt u een foutmelding. De volgende code werkt bijvoorbeeld niet:

package main

import "fmt"

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

Wanneer u de voorgaande code uitvoert, krijgt u de volgende fout:

panic: assignment to entry in nil map

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

Als u problemen wilt voorkomen wanneer u items aan een kaart toevoegt, moet u een lege kaart (geen nil kaart) maken met behulp van de make functie zoals we in het vorige codefragment hebben laten zien. Deze regel geldt alleen wanneer u items toevoegt. Als u zoekopdrachten, verwijderingen of lusbewerkingen in een nil kaart uitvoert, raakt Go niet in paniek. We bevestigen dat gedrag binnen een ogenblik.

Toegang tot items

Voor toegang tot items in een kaart gebruikt u de gebruikelijke subscript-notatie m[key], zoals bij matrices of segmenten. Hier volgt een eenvoudig voorbeeld van hoe u toegang krijgt tot een item:

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"])
}

Wanneer u de subscript-notatie in een kaart gebruikt, krijgt u altijd een antwoord terug, zelfs als de sleutel niet aanwezig is op een kaart. Go raakt niet in paniek wanneer u toegang krijgt tot een item dat niet bestaat. In plaats daarvan krijgt u de standaardwaarde terug. U kunt dit gedrag bevestigen met behulp van de volgende code:

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"])
}

Wanneer u de voorgaande code uitvoert, ziet u de volgende uitvoer:

Christy's age is 0

In veel gevallen is het eerlijk dat Go geen fout retourneert wanneer u toegang krijgt tot een item dat niet bestaat in een kaart. Maar er zijn momenten waarop u moet weten of een item al dan niet bestaat. In Go kan de subscript-notatie voor een kaart twee waarden opleveren. De eerste is de waarde van een item. De tweede is een Booleaanse vlag die aangeeft of de sleutel al dan niet bestaat.

U kunt het probleem met het laatste codefragment oplossen door de volgende code te gebruiken:

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")
    }
}

Wanneer u de voorgaande code uitvoert, ziet u de volgende uitvoer:

Christy's age couldn't be found

Gebruik het tweede codefragment om te controleren of er een sleutel in een kaart bestaat voordat u deze opent.

Items verwijderen

Als u een item uit een kaart wilt verwijderen, gebruikt u de ingebouwde delete() functie. Hier volgt een voorbeeld van het verwijderen van items uit een kaart:

package main

import "fmt"

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

Wanneer u de code uitvoert, krijgt u de volgende uitvoer:

map[bob:31]

Zoals we eerder hebben gezegd, raakt Go niet in paniek als u probeert een item te verwijderen dat niet bestaat. Hier volgt een voorbeeld van dat gedrag:

package main

import "fmt"

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

Wanneer u de code uitvoert, krijgt u geen foutmelding en ziet u de volgende uitvoer:

map[bob:31 john:32]

Lus in een kaart

Laten we ten slotte eens kijken hoe u een lus op een kaart kunt uitvoeren om programmatisch toegang te krijgen tot alle items. Hiervoor kunt u de op bereik gebaseerde lus gebruiken, zoals in dit voorbeeld:

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)
    }
}

Wanneer u de voorgaande code uitvoert, ziet u de volgende uitvoer:

john    32
bob     31

U ziet hoe u de sleutel- en waardegegevens in verschillende variabelen kunt opslaan. In dit geval houden we de sleutel in de name variabele en de waarde in de age variabele vast. range Geeft dus eerst de sleutel van een item op en ten tweede de waarde van dat item. U kunt een van beide negeren met behulp van de _ variabele, zoals in dit voorbeeld:

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)
    }
}

Hoewel het in dit geval niet zinvol is om de leeftijden op die manier af te drukken, zijn er gevallen waarin u de sleutel van een item niet hoeft te kennen. U kunt ook alleen de sleutel van het item gebruiken, zoals in dit voorbeeld:

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)
    }
}