Cvičení – použití map
Mapa v Go je v podstatě hashovací tabulka, což je kolekce párů klíč-hodnota. Všechny klíče v mapě musí být stejného typu, a proto hodnoty. Pro klíče a hodnoty ale můžete použít různé typy. Například klíče můžou být čísla a hodnoty můžou být řetězce. Pokud chcete získat přístup k určité položce v mapě, odkazujete na jeho klíč.
Deklarace a inicializace mapy
Pokud chcete deklarovat mapu, musíte použít map
klíčové slovo. Pak definujete klíč a typ hodnoty, například takto: map[T]T
. Pokud například chcete vytvořit mapu obsahující věk studentů, můžete použít následující kód:
package main
import "fmt"
func main() {
studentsAge := map[string]int{
"john": 32,
"bob": 31,
}
fmt.Println(studentsAge)
}
Při spuštění předchozího kódu se zobrazí následující výstup:
map[bob:31 john:32]
Pokud nechcete inicializovat mapu s položkami, můžete pomocí integrované make()
funkce vytvořit mapu v předchozí části. K vytvoření prázdné mapy můžete použít následující kód:
studentsAge := make(map[string]int)
Mapy jsou dynamické. Po jejich vytvoření můžete přidávat, přistupovat k nim nebo je odebírat. Pojďme se na tyto akce podívat.
Přidat položky
Pokud chcete přidat položky, nemusíte používat předdefinované funkce, jako to děláte s řezy. Mapy jsou jednodušší. Stačí definovat klíč a hodnotu. Pokud pár neexistuje, položka se přidá do mapy.
Pojďme přepsat kód, který jsme použili dříve k vytvoření mapy pomocí make
funkce. Pak přidáme položky do mapy. Můžete použít následující kód:
package main
import "fmt"
func main() {
studentsAge := make(map[string]int)
studentsAge["john"] = 32
studentsAge["bob"] = 31
fmt.Println(studentsAge)
}
Při spuštění kódu získáte stejný výstup jako předtím:
map[bob:31 john:32]
Všimněte si, že jsme přidali položky do mapy, která byla inicializována. Pokud se ale pokusíte provést totéž s mapou nil
, zobrazí se chyba. Například následující kód nebude fungovat:
package main
import "fmt"
func main() {
var studentsAge map[string]int
studentsAge["john"] = 32
studentsAge["bob"] = 31
fmt.Println(studentsAge)
}
Při spuštění předchozího kódu se zobrazí následující chyba:
panic: assignment to entry in nil map
goroutine 1 [running]:
main.main()
/Users/johndoe/go/src/helloworld/main.go:7 +0x4f
exit status 2
Abyste se vyhnuli problémům při přidávání položek do mapy, ujistěte se, že vytvoříte prázdnou mapu (ne nil
mapu) pomocí make
funkce, jako jsme ukázali v předchozím fragmentu kódu. Toto pravidlo platí jenom při přidávání položek. Pokud spustíte operace vyhledávání, odstranění nebo smyčky na mapě nil
, Go nebude panice. Toto chování potvrdíme za chvíli.
Přístup k položkám
Pokud chcete získat přístup k položkám v mapě, použijte obvyklý zápis dolního indexu m[key]
, jako je tomu u polí nebo řezů. Tady je jednoduchý příklad přístupu k položce:
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"])
}
Při použití zápisu dolního indexu v mapě se vždy vrátí odpověď, i když klíč není na mapě. Při přístupu k položce, která neexistuje, nejde přejít k panice. Místo toho se vrátí výchozí hodnota. Toto chování můžete potvrdit pomocí následujícího kódu:
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"])
}
Při spuštění předchozího kódu se zobrazí následující výstup:
Christy's age is 0
V mnoha případech je spravedlivé, že Go nevrátí chybu, když přistupujete k položce, která v mapě neexistuje. Někdy ale potřebujete vědět, jestli položka existuje nebo ne. Zápis dolního indexu pro mapu může v go přinést dvě hodnoty. První je hodnota položky. Druhým příznakem je logický příznak, který označuje, jestli klíč existuje nebo ne.
K vyřešení problému s posledním fragmentem kódu můžete použít následující kód:
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")
}
}
Při spuštění předchozího kódu se zobrazí následující výstup:
Christy's age couldn't be found
Pomocí druhého fragmentu kódu zkontrolujte, jestli klíč v mapě existuje, než k němu přistupujete.
Odebrání položek
Pokud chcete odebrat položku z mapy, použijte integrovanou delete()
funkci. Tady je příklad odebrání položek z mapy:
package main
import "fmt"
func main() {
studentsAge := make(map[string]int)
studentsAge["john"] = 32
studentsAge["bob"] = 31
delete(studentsAge, "john")
fmt.Println(studentsAge)
}
Při spuštění kódu získáte následující výstup:
map[bob:31]
Jak jsme řekli dříve, pokud se pokusíte odstranit položku, která neexistuje, Go nebude panice. Tady je příklad tohoto chování:
package main
import "fmt"
func main() {
studentsAge := make(map[string]int)
studentsAge["john"] = 32
studentsAge["bob"] = 31
delete(studentsAge, "christy")
fmt.Println(studentsAge)
}
Při spuštění kódu se nezobrazí chyba a zobrazí se následující výstup:
map[bob:31 john:32]
Smyčka v mapě
Nakonec se podíváme, jak můžete v mapě smyčce získat přístup ke všem položkám prostřednictvím kódu programu. K tomu můžete použít smyčku založenou na rozsahu, například v tomto příkladu:
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)
}
}
Při spuštění předchozího kódu se zobrazí následující výstup:
john 32
bob 31
Všimněte si, jak můžete uložit informace o klíči a hodnotě v různých proměnných. V tomto případě držíme klíč v name
proměnné a hodnotu v age
proměnné.
range
Získá tedy první klíč položky a druhou hodnotu této položky. Některou z nich můžete ignorovat pomocí proměnné, například v tomto příkladu _
:
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)
}
}
I když v tomto případě nemá smysl tisknout věky tímto způsobem, budou existovat případy, kdy nepotřebujete znát klíč položky. Alternativně můžete použít jenom klíč položky, například tento příklad:
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)
}
}