Achtergrond van de vraag:
Go heeft van nature geen Set-structuur, maar vaak ontstaat de behoefte om met unieke elementen te werken. De optimale structuur is map[string]struct{}, waarbij de sleutel het element is en de lege structuur dient als "aanwezigheidslabel". Dit is een veelvoorkomend patroon voor een snelle lidmaatschapstest.
Probleem:
Het gebrek aan een ingebouwde Set leidt ertoe dat beginners het moeilijk vinden om unieke collecties correct te implementeren. Men moet ook begrijpen waarom struct{} efficiënter is dan bool of int als waarde.
Oplossing:
Om een Set in Go te implementeren, gebruiken we map[string]struct{}. De lege structuur struct{} vereist geen geheugen (zero-sized), en de map biedt snelle toegang. Voorbeeld:
set := make(map[string]struct{}) set["foo"] = struct{}{} if _, ok := set["foo"]; ok { fmt.Println("Aanwezig") } delete(set, "foo")
Belangrijkste kenmerken:
Waarom kan je geen slice/array gebruiken als waarde?
slice/array voor een set biedt geen constante tijd voor het zoeken van een element - je zou alle waarden moeten doorlopen, wat traag is.
Wat is het verschil tussen map[string]struct{} en map[string]bool?
map[string]bool verbruikt meer geheugen: voor elke sleutel wordt een bool opgeslagen, terwijl struct{} een lege type is dat niets alloceert.
set := map[string]bool{"foo": true}
Kan ik int gebruiken in plaats van struct{}?
Ja, maar int vereist altijd geheugen. struct{} is veelzijdiger: als je alleen de rol van "label" (aanwezigheid) nodig hebt, is het beter.
set := map[string]int{"foo": 1} // maar slaat (sleutel -> nummer) op
Door onwetendheid is map[string]bool toegewezen voor een set unieke IP-adressen. Dit leidde tot een verdubbeling van het geheugenverbruik in vergelijking met struct{} bij miljoenen adressen.
Voordelen:
Nadelen:
In een project werd map[string]struct{} gebruikt voor het opslaan van unieke e-mails. De belasting nam af, het werkte sneller en verbruikte bijna geen geheugen voor waarden.
Voordelen:
Nadelen: