Ćwiczenie — korzystanie z map

Ukończone

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