ProgrammationDéveloppeur Go

Comment fonctionne map[string]struct{} comme ensemble en Go et quelles sont les particularités de cette utilisation ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Historique de la question :

Go n’a pas de structure Set par défaut, mais il est souvent nécessaire de travailler avec des éléments uniques. La structure optimale est map[string]struct{}, où la clé est l’élément et la structure vide sert de "marqueur de présence". C'est un motif courant pour un test d'appartenance rapide.

Problème :

L'absence d'un Set intégré rend difficile pour les débutants de réaliser correctement des collections uniques. Il est également important de comprendre pourquoi struct{} est plus efficace que bool ou int en tant que valeur.

Solution :

Pour implémenter un Set en Go, on utilise map[string]struct{}. La structure vide struct{} ne nécessite pas de mémoire (taille nulle), tandis que la map offre un accès rapide. Exemple :

set := make(map[string]struct{}) set["foo"] = struct{}{} if _, ok := set["foo"]; ok { fmt.Println("Présent") } delete(set, "foo")

Caractéristiques clés :

  • struct{} occupe 0 octet — implémentation économique
  • map offre un accès O(1) par clé
  • Pas de duplication d'éléments, la sémantique du Set est facilement réalisable

Questions pièges.

Pourquoi ne pas utiliser un slice/tableau comme valeur ?

Un slice/tableau pour un set ne permet pas une recherche d'élément en temps constant — il faudra parcourir toutes les valeurs, ce qui est lent.

Quelle est la différence entre map[string]struct{} et map[string]bool ?

map[string]bool consomme plus de mémoire : pour chaque clé, on stocke un booléen, alors que struct{} — type vide, n’alloue rien.

set := map[string]bool{"foo": true}

Peut-on utiliser int à la place de struct{} ?

Oui, mais int occupe toujours de la mémoire. struct{} est universel : si l’on a juste besoin d’un "marqueur" (de présence), il est préférable.

set := map[string]int{"foo": 1} // mais stocke (clé -> nombre)

Erreurs typiques et anti-modèles

  • Utiliser bool ou int pour des valeurs sans nécessité
  • Utiliser un slice pour rechercher la présence d’un élément (ralentit les vérifications)
  • Oublier de supprimer des éléments avec delete

Exemple de la vie réelle

Cas négatif

En raison d’un manque de connaissance, un map[string]bool a été choisi pour un ensemble d’adresses IP uniques. En conséquence, avec des millions d'adresses, la consommation mémoire a doublé par rapport à struct{}.

Avantages :

  • Sémantiquement clair (true == présent)

Inconvénients :

  • Performance inférieure
  • Consommation de mémoire supérieure

Cas positif

Dans un projet, pour stocker des emails uniques, on a utilisé map[string]struct{}. La charge a diminué, le fonctionnement est plus rapide, la mémoire presque pas utilisée pour les valeurs.

Avantages :

  • Surcharge minimale
  • Performance avec un grand nombre d'éléments

Inconvénients :

  • Moins évident pour les débutants, nécessite des commentaires dans le code