Ćwiczenie — korzystanie z map
Mapa w języku Go jest w zasadzie tabelą skrótów, która jest kolekcją par klucz i wartość. Wszystkie klucze na mapie muszą być tego samego typu, a więc należy wykonać te wartości. Można jednak użyć różnych typów dla kluczy i wartości. Na przykład klucze mogą być liczbami, a wartościami mogą być ciągi. Aby uzyskać dostęp do określonego elementu na mapie, należy odwołać się do jego klucza.
Deklarowanie i inicjowanie mapy
Aby zadeklarować mapę, musisz użyć słowa kluczowego map
. Następnie zdefiniuj klucz i typ wartości w następujący sposób: map[T]T
. Jeśli na przykład chcesz utworzyć mapę zawierającą wiek uczniów, możesz użyć następującego kodu:
package main
import "fmt"
func main() {
studentsAge := map[string]int{
"john": 32,
"bob": 31,
}
fmt.Println(studentsAge)
}
Po uruchomieniu poprzedniego kodu zobaczysz następujące dane wyjściowe:
map[bob:31 john:32]
Jeśli nie chcesz inicjować mapy za pomocą elementów, możesz użyć wbudowanej make()
funkcji , aby utworzyć mapę w poprzedniej sekcji. Aby utworzyć pustą mapę, możesz użyć następującego kodu:
studentsAge := make(map[string]int)
Mapy są dynamiczne. Możesz dodawać, uzyskiwać dostęp lub usuwać elementy po ich utworzeniu. Przyjrzyjmy się tym akcjom.
Dodaj elementy
Aby dodać elementy, nie musisz używać wbudowanej funkcji, takiej jak w przypadku wycinków. Mapy są prostsze. Musisz tylko zdefiniować klucz i wartość. Jeśli para nie istnieje, element zostanie dodany do mapy.
Napiszmy ponownie kod użyty wcześniej do utworzenia mapy przy użyciu make
funkcji . Następnie dodamy elementy do mapy. Możesz użyć następującego kodu:
package main
import "fmt"
func main() {
studentsAge := make(map[string]int)
studentsAge["john"] = 32
studentsAge["bob"] = 31
fmt.Println(studentsAge)
}
Po uruchomieniu kodu uzyskasz te same dane wyjściowe co poprzednio:
map[bob:31 john:32]
Zwróć uwagę, że dodaliśmy elementy do mapy, która została zainicjowana. Jeśli jednak spróbujesz wykonać to samo za pomocą nil
mapy, zostanie wyświetlony błąd. Na przykład następujący kod nie będzie działać:
package main
import "fmt"
func main() {
var studentsAge map[string]int
studentsAge["john"] = 32
studentsAge["bob"] = 31
fmt.Println(studentsAge)
}
Po uruchomieniu poprzedniego kodu zostanie wyświetlony następujący błąd:
panic: assignment to entry in nil map
goroutine 1 [running]:
main.main()
/Users/johndoe/go/src/helloworld/main.go:7 +0x4f
exit status 2
Aby uniknąć problemów podczas dodawania elementów do mapy, upewnij się, że utworzono pustą nil
mapę (a nie mapę) przy użyciu make
funkcji, takiej jak pokazano w poprzednim fragmencie kodu. Ta reguła ma zastosowanie tylko w przypadku dodawania elementów. Jeśli uruchamiasz operacje wyszukiwania, usuwania lub pętli na nil
mapie, język Go nie będzie panikować. Za chwilę potwierdzimy to zachowanie.
Elementy dostępu
Aby uzyskać dostęp do elementów na mapie, użyj zwykłej notacji m[key]
w indeksie dolnym , tak jak w przypadku tablic lub wycinków. Oto prosty przykład sposobu uzyskiwania dostępu do elementu:
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"])
}
Jeśli używasz notacji indeksu dolnego na mapie, zawsze otrzymujesz odpowiedź z powrotem, nawet jeśli klucz nie jest obecny na mapie. Przejście nie powoduje paniki, gdy uzyskujesz dostęp do elementu, który nie istnieje. Zamiast tego uzyskasz wartość domyślną z powrotem. To zachowanie można potwierdzić przy użyciu następującego kodu:
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"])
}
Po uruchomieniu poprzedniego kodu zobaczysz następujące dane wyjściowe:
Christy's age is 0
W wielu przypadkach jest sprawiedliwe, że język Go nie zwraca błędu, gdy uzyskujesz dostęp do elementu, który nie istnieje na mapie. Ale czasami musisz wiedzieć, czy element istnieje, czy nie. W języku Go notacja w indeksie dolnym mapy może przynieść dwie wartości. Pierwszy to wartość elementu. Drugi to flaga logiczna wskazująca, czy klucz istnieje, czy nie.
Aby rozwiązać problem z ostatnim fragmentem kodu, możesz użyć następującego kodu:
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")
}
}
Po uruchomieniu poprzedniego kodu zobaczysz następujące dane wyjściowe:
Christy's age couldn't be found
Użyj drugiego fragmentu kodu, aby sprawdzić, czy klucz na mapie istnieje przed uzyskaniem do niego dostępu.
Usuń elementy
Aby usunąć element z mapy, użyj wbudowanej delete()
funkcji. Oto przykład usuwania elementów 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)
}
Po uruchomieniu kodu uzyskasz następujące dane wyjściowe:
map[bob:31]
Jak powiedzieliśmy wcześniej, jeśli spróbujesz usunąć element, który nie istnieje, Go nie panikuje. Oto przykład tego zachowania:
package main
import "fmt"
func main() {
studentsAge := make(map[string]int)
studentsAge["john"] = 32
studentsAge["bob"] = 31
delete(studentsAge, "christy")
fmt.Println(studentsAge)
}
Po uruchomieniu kodu nie zostanie wyświetlony błąd i zobaczysz następujące dane wyjściowe:
map[bob:31 john:32]
Pętla na mapie
Na koniec zobaczmy, jak można utworzyć pętlę na mapie, aby uzyskać dostęp do wszystkich jego elementów programowo. W tym celu można użyć pętli opartej na zakresie, takiej jak w tym przykładzie:
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)
}
}
Po uruchomieniu poprzedniego kodu zobaczysz następujące dane wyjściowe:
john 32
bob 31
Zwróć uwagę, że informacje o kluczu i wartości można przechowywać w różnych zmiennych. W tym przypadku trzymamy klucz w zmiennej name
i wartość w zmiennej age
. range
Daje więc najpierw klucz elementu, a po drugie wartość tego elementu. Możesz zignorować jedną z nich przy użyciu zmiennej _
, takiej jak w tym przykładzie:
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)
}
}
Mimo że w tym przypadku nie ma sensu drukować wieków w ten sposób, będą przypadki, w których nie musisz znać klucza elementu. Alternatywnie możesz użyć tylko klucza elementu, takiego jak w tym przykładzie:
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)
}
}