Övning – Använda kartor
En karta i Go är i princip en hash-tabell, som är en samling nyckel- och värdepar. Alla nycklar på en karta måste vara av samma typ, och det gör även värdena. Men du kan använda olika typer för nycklar och värden. Nycklar kan till exempel vara tal och värdena kan vara strängar. Om du vill komma åt ett visst objekt på en karta refererar du till dess nyckel.
Deklarera och initiera en karta
Om du vill deklarera en karta måste du använda nyckelordet map
. Sedan definierar du nyckel- och värdetypen, så här: map[T]T
. Om du till exempel vill skapa en karta som innehåller elevernas ålder kan du använda följande kod:
package main
import "fmt"
func main() {
studentsAge := map[string]int{
"john": 32,
"bob": 31,
}
fmt.Println(studentsAge)
}
När du kör föregående kod visas följande utdata:
map[bob:31 john:32]
Om du inte vill initiera en karta med objekt kan du använda den inbyggda make()
funktionen för att skapa kartan i föregående avsnitt. Du kan använda följande kod för att skapa en tom karta:
studentsAge := make(map[string]int)
Kartor är dynamiska. Du kan lägga till, komma åt eller ta bort objekt när du har skapat dem. Nu ska vi utforska dessa åtgärder.
Lägg till objekt
Om du vill lägga till objekt behöver du inte använda en inbyggd funktion som du gör med sektorer. Kartor är enklare. Du behöver bara definiera en nyckel och ett värde. Om paret inte finns läggs objektet till på kartan.
Nu ska vi skriva om koden som vi använde tidigare för att skapa en karta med hjälp make
av funktionen . Sedan lägger vi till objekt på kartan. Du kan använda följande kod:
package main
import "fmt"
func main() {
studentsAge := make(map[string]int)
studentsAge["john"] = 32
studentsAge["bob"] = 31
fmt.Println(studentsAge)
}
När du kör koden får du samma utdata som tidigare:
map[bob:31 john:32]
Observera att vi har lagt till objekt på en karta som initierades. Men om du försöker göra samma sak med en nil
karta får du ett fel. Följande kod fungerar till exempel inte:
package main
import "fmt"
func main() {
var studentsAge map[string]int
studentsAge["john"] = 32
studentsAge["bob"] = 31
fmt.Println(studentsAge)
}
När du kör föregående kod får du följande fel:
panic: assignment to entry in nil map
goroutine 1 [running]:
main.main()
/Users/johndoe/go/src/helloworld/main.go:7 +0x4f
exit status 2
Om du vill undvika problem när du lägger till objekt i en karta måste du skapa en tom karta (inte en nil
karta) med hjälp av funktionen make
som vi visade i föregående kodfragment. Den här regeln gäller endast när du lägger till objekt. Om du kör sökningar, borttagningar eller loopåtgärder på en nil
karta får Go inte panik. Vi bekräftar det beteendet om en stund.
Åtkomstobjekt
Om du vill komma åt objekt i en karta använder du den vanliga nedsänkta notationen m[key]
, som du gör med matriser eller sektorer. Här är ett enkelt exempel på hur du kommer åt ett objekt:
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"])
}
När du använder den nedsänkta notationen på en karta får du alltid ett svar tillbaka, även om nyckeln inte finns på en karta. Go får inte panik när du kommer åt ett objekt som inte finns. I stället får du tillbaka standardvärdet. Du kan bekräfta det beteendet med hjälp av följande kod:
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"])
}
När du kör föregående kod visas följande utdata:
Christy's age is 0
I många fall är det rättvist att Go inte returnerar ett fel när du kommer åt ett objekt som inte finns på en karta. Men det finns tillfällen då du behöver veta om ett objekt finns eller inte. I Go kan den nedsänkta notationen för en karta ge två värden. Den första är värdet för ett objekt. Den andra är en boolesk flagga som anger om nyckeln finns eller inte.
Om du vill åtgärda problemet med det senaste kodfragmentet kan du använda följande kod:
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")
}
}
När du kör föregående kod visas följande utdata:
Christy's age couldn't be found
Använd det andra kodfragmentet för att kontrollera om det finns en nyckel i en karta innan du kommer åt den.
Ta bort objekt
Om du vill ta bort ett objekt från en karta använder du den inbyggda delete()
funktionen. Här är ett exempel på hur du tar bort objekt från en karta:
package main
import "fmt"
func main() {
studentsAge := make(map[string]int)
studentsAge["john"] = 32
studentsAge["bob"] = 31
delete(studentsAge, "john")
fmt.Println(studentsAge)
}
När du kör koden får du följande utdata:
map[bob:31]
Som vi sa tidigare, om du försöker ta bort ett objekt som inte finns, kommer Go inte att få panik. Här är ett exempel på det beteendet:
package main
import "fmt"
func main() {
studentsAge := make(map[string]int)
studentsAge["john"] = 32
studentsAge["bob"] = 31
delete(studentsAge, "christy")
fmt.Println(studentsAge)
}
När du kör koden får du inget fel och du ser följande utdata:
map[bob:31 john:32]
Loopa på en karta
Slutligen ska vi se hur du kan loopa i en karta för att komma åt alla dess objekt programmatiskt. För att göra det kan du använda den intervallbaserade loopen, som i det här exemplet:
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)
}
}
När du kör föregående kod visas följande utdata:
john 32
bob 31
Observera hur du kan lagra nyckel- och värdeinformationen i olika variabler. I det här fallet håller vi nyckeln i variabeln name
och värdet i variabeln age
. range
Så ger först nyckeln för ett objekt, och för det andra värdet för objektet. Du kan ignorera någon av dem med hjälp av variabeln _
, som i det här exemplet:
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)
}
}
Även om det i det här fallet inte är meningsfullt att skriva ut åldrarna på det sättet, kommer det att finnas fall där du inte behöver känna till nyckeln för ett objekt. Du kan också bara använda objektets nyckel, som i det här exemplet:
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)
}
}