In Go ist der Typ struct{} eine Struktur ohne Felder und benötigt 0 Bytes Speicher. Dies ist eine wertvolle Eigenschaft, die genutzt wird, um den Ressourcenverbrauch zu minimieren, wenn das Vorhandensein von etwas wichtig ist, aber keine Daten benötigt werden — zum Beispiel bei der Implementierung von Mengen (set), Signalstrukturen oder Ereigniskanälen.
Beispiel zur Verwendung für Mengen:
mySet := make(map[string]struct{}) mySet["foo"] = struct{}{} if _, ok := mySet["foo"]; ok { fmt.Println("foo ist in mySet vorhanden") }
struct{} wird als Wert verwendet, um die Anwesenheit eines Schlüssels anzuzeigen.map[string]bool ist die Variante mit struct{} speichereffizienter.Kanäle für Signale:
done := make(chan struct{}) // Die Goroutine wartet auf das Abschluss-Signal <-done
Was ist der Unterschied zwischen map[string]struct{} und map[string]bool bei der Implementierung von Mengen? Warum ist map[string]struct{} vorzuziehen und hat es Nachteile?
Antwort:
map[string]struct{} verwendet 0 Bytes für den Wert, die kompakteste Variante — spart Speicher, besonders bei großen Datenmengen.map[string]bool benötigt 1 Byte für den Wert (intern kann es aufgrund der Ausrichtung dennoch mehr Speicher verbrauchen).map[string]struct{}: Es ist nicht einfach, eine Liste aller als true markierten Werte zu erhalten, falls ein boolescher Wert benötigt wird. Es muss trotzdem über die Schlüssel iteriert werden.Beispiel:
set := make(map[string]struct{}) set["Alice"] = struct{}{} _, exists := set["Alice"] // true flags := make(map[string]bool) flags["Alice"] = true _, exists := flags["Alice"] // true
Geschichte
In einem Projekt zur Speicherung einzigartiger Identifikatoren wurde map[string]bool verwendet, was mit zunehmenden Daten zu einem erheblichen Anstieg des Speicherbedarfs führte — Hundert Megabyte im Vergleich zur Variante mit map[string]struct{}. Der Umstieg auf struct{} reduzierte den Speicherbedarf um mehr als das Doppelte.
Geschichte
Ein Anfänger signalisierte den Abschluss einer Goroutine über
chan bool. Bei einer großen Anzahl von Goroutinen erwies sich die Übertragung des Wertes als überflüssig: Es wurde nirgendwo analysiert, obtrueoderfalsegesendet wurde. Der Umstieg aufchan struct{}zeigte eine architektonische Ungenauigkeit und vereinfachte den Code.
Geschichte
In einer Bibliothek wurde eine Menge über map implementiert, bei der als Wert string verwendet wurde. Dies benötigte zu viel Speicher. Nach einer Code-Überprüfung wurde auf map[typ]struct{} umgestellt. Der Fehler wurde nach der Analyse des Speicherprofils bei Lasttests festgestellt, als die Anwendung aufgrund von OOM abstürzte.