W Go typ struct{} reprezentuje strukturę bez pól i zajmuje 0 bajtów pamięci. To cenna cecha, wykorzystywana do minimalizacji zużycia zasobów w przypadkach, gdy ważny jest fakt istnienia czegoś, ale nie są potrzebne dane — na przykład w implementacji zbiorów (set), struktur sygnalizacyjnych lub kanałów do zdarzeń.
Przykład użycia dla zbioru:
mySet := make(map[string]struct{}) mySet["foo"] = struct{}{} if _, ok := mySet["foo"]; ok { fmt.Println("foo jest obecne w mySet") }
struct{} jest używane jako wartość, aby pokazać obecność klucza.map[string]bool, wersja z struct{} jest bardziej oszczędna pod względem pamięci.Kanały do sygnalizacji:
done := make(chan struct{}) // Gorutyna czeka na sygnał zakończenia <-done
Czym różni się map[string]struct{} od map[string]bool przy implementacji zbioru? Dlaczego map[string]struct{} jest bardziej preferowane i czy ma jakieś wady?
Odpowiedź:
map[string]struct{} używa 0 bajtów na wartość, co jest najbardziej kompaktową wersją — oszczędza pamięć, szczególnie przy dużej ilości danych.map[string]bool wymaga 1 bajta na wartość (wewnętrznie i tak może zajmować więcej pamięci z powodu wyrównania).map[string]struct{}: nie można szybko uzyskać listy wszystkich wartości oznaczonych jako true, jeśli nagle zajdzie potrzeba logicznej wartości. I tak trzeba przeszukać klucze.Przykład:
set := make(map[string]struct{}) set["Alice"] = struct{}{} _, exists := set["Alice"] // true flags := make(map[string]bool) flags["Alice"] = true _, exists := flags["Alice"] // true
Historia
W projekcie do przechowywania unikalnych identyfikatorów używano map[string]bool, co w miarę wzrostu danych doprowadziło do znacznego wzrostu zużycia pamięci — setki megabajtów w porównaniu z wersją na map[string]struct{}. Przełączając się na struct{}, zmniejszono zużycie pamięci o ponad połowę.
Historia
Nowicjusz sygnalizował zakończenie gorutyny przez
chan bool. Przy dużej liczbie gorutin przesyłanie wartości okazało się zbędne: nigdzie nie analizowano, czy przyszedłtrueczyfalse. Zastąpienie nachan struct{}ujawniło niedokładność architektoniczną i pozwoliło uprościć kod.
Historia
W bibliotece tworzono zbiór przez mapę, gdzie jako wartość używano string. Zajmowało to zbyt dużo pamięci. Po Code Review przestawiono na map[typ]struct{}. Błąd ujawniono po analizie profilu pamięci podczas testów obciążeniowych, gdy aplikacja padła z powodu OOM.