Sobes.tech
Middle

Jak działa mapa w Go?

sobes.tech AI

Odpowiedź od AI

Mapa w Go jest zaimplementowana jako tablica mieszająca.

Główne składniki struktury map:

  • Funkcja haszująca: Mapuje klucze na wartości haszujące (liczby całkowite).
  • Tablica kubełków: Zbiór list lub tablic, w których przechowywane są pary klucz-wartość. Indeks kubełka jest określany przez wartość haszującą klucza.
  • Obsługa kolizji: Gdy różne klucze mają ten sam hash (kolizja), elementy z tymi kluczami są przechowywane w tym samym kubełku, zwykle w postaci listy powiązanej lub kubełka nadmiarowego.
  • Współczynnik obciążenia: Stosunek liczby elementów do liczby kubełków. Po przekroczeniu pewnego progu następuje rehaszowanie: tworzy się nową, większą tablicę kubełków i przenosi wszystkie elementy ze starych kubełków do nowych.

Struktura map w Go jest reprezentowana przez typ hmap:

 type hmap struct {
    count     int // Liczba elementów
    flags     uint8 // Flagi stanu
    B         uint8 // log_2 liczby kubełków (liczba kubełków to 2^B)
    noverflow uint16 // Liczba kubełków z nadmiarem (tylko do statystyk)
    hash0     uint32 // Wartość początkowa funkcji haszującej

    buckets    unsafe.Pointer // Wskaźnik na tablicę kubełków (główne i nadmiarowe)
    oldbuckets unsafe.Pointer // Wskaźnik na starą tablicę kubełków podczas migracji
    nevacuate  uintptr // Określa, do którego starego kubełka zakończyła się migracja

    extra *mapextra // Dodatkowe informacje (opcjonalnie)
}

 type mapextra struct {
    overflow    *[2]*[]*bmap // Wskaźniki na tablice nadmiarowych kubełków
    oldoverflow *[2]*[]*bmap // Wskaźniki na stare tablice nadmiarowych kubełków
    nextOverflow *bmap // Następny wolny nadmiarowy kubełek
}

 type bmap struct {
    tophash [8]uint8 // Top-hash (górne bity hasza) dla przyspieszenia wyszukiwania w kubełku
    // Następują klucze, wartości i wskaźniki na następny bmap (jeśli kubełek jest przepełniony)
    // rozkład wszystkich danych dla hmap.buckets w jednym malloc
    // patrz ../../runtime/map.go dla szczegółów
}

Operacje:

  • Wstawianie/aktualizacja: Oblicza się hash klucza, określa kubełek. Jeśli klucz już istnieje, wartość jest aktualizowana. W przeciwnym razie, para klucz-wartość jest dodawana do kubełka. Przy przepełnieniu kubełka lub przekroczeniu Load Factor może nastąpić rehaszowanie.
  • Wyszukiwanie: Oblicza się hash klucza, określa kubełek. Elementy w kubełku są przeszukiwane po top-hash, następnie porównywane są pełne klucze. Zwracana jest wartość i flaga istnienia.
  • Usuwanie: Oblicza się hash klucza, określa kubełek. Element jest oznaczany jako usunięty (ale nie jest natychmiast usuwany z pamięci). Usunięcie następuje podczas operacji późniejszych lub rehaszowania.

Mapa w Go nie jest synchronizowana i nie może być bezpiecznie używana przez wiele gorutyn bez zewnętrznej synchronizacji.