Enums en Go : manière idiomatique et magie sous le capot

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction : pourquoi Go ne dit-il pas « enum » ?

\n\n

Si vous venez à Go depuis Python, Java ou C#, vous avez probablement eu un léger choc culturel : Go n'a pas de mot-clé enum. Pas d'énumérations intégrées avec numérotation automatique, pas de méthodes .name() ou .valueOf(). Juste vous, le compilateur et… des constantes.

\n\n

La question « What is an idiomatic way of representing enums in Go? » est l'une des plus populaires sur Stack Overflow dans la section Golang (des milliers de vues). Et ce n'est pas un hasard. Chaque débutant finit tôt ou tard par se heurter à un mur : « Comment faire un enum de manière go-esque ? ».

\n\n

Dans cet article, nous ne donnons pas seulement une réponse. Nous regardons sous le capot : comment Go traite les constantes, ce qu'est iota et pourquoi le compilateur ne considère pas deux valeurs int différentes comme des types différents. Et à la fin, vous apprendrez à rendre un enum sûr, pratique et élégant.

\n\n

Le problème : pourquoi les simples constantes sont-elles mauvaises ?

\n\n

La première chose qui vient à l'esprit est de déclarer plusieurs constantes :

\n\n
const (\n    StatusActive   = 1\n    StatusInactive = 2\n    StatusPending  = 3\n)
\n\n

Cela semble fonctionner. Mais il y a un hic : toute fonction qui accepte un int acceptera la valeur 999 ou -42. Le compilateur ne dira rien. Ce n'est pas une énumération — ce sont juste des nombres avec des noms.

\n\n

Un véritable enum doit :

\n
    \n
  • Limiter l'ensemble des valeurs autorisées ;
  • \n
  • Être type-safe (on ne peut pas passer un int là où un statut est attendu) ;
  • \n
  • Être lisible et facilement extensible.
  • \n
\n\n

Go résout ce problème de manière idiomatique : via des types personnalisés et iota.

\n\n

La manière idiomatique : type + iota

\n\n

Voici à quoi ressemble la réponse canonique de ce fameux Stack Overflow :

\n\n
type Status int\n\nconst (\n    StatusActive   Status = iota // 0\n    StatusInactive               // 1\n    StatusPending                // 2\n    StatusDeleted                // 3\n)
\n\n

Que s'est-il passé ici ?

\n
    \n
  • type Status int — nous avons créé un nouveau type nommé. Oui, sous le capot c'est un int, mais pour le compilateur, Status et int sont des choses différentes.
  • \n
  • iota est un générateur de nombres entiers consécutifs qui fonctionne uniquement à l'intérieur d'un bloc const. Chaque nouvelle ligne augmente la valeur de 1.
  • \n
\n\n

Maintenant, une fonction qui accepte un Status ne compilera pas si vous essayez de lui passer un int ordinaire :

\n\n
func Process(s Status) {\n    // ...\n}\n\nfunc main() {\n    Process(StatusActive) // OK\n    Process(1)            // Erreur de compilation ! Cannot use 1 (type int) as type Status\n}
\n\n

C'est ce qu'on appelle la type-safety — la première et principale raison d'utiliser des types personnalisés pour les enums.

\n\n

Pourquoi iota plutôt qu'une numérotation manuelle ?

\n\n

Imaginez que vous ajoutiez un nouveau statut au milieu de la liste. Avec une numérotation manuelle, vous devriez réécrire toutes les valeurs suivantes. iota le fait automatiquement. Ce n'est pas seulement pratique — c'est idiomatique.

\n\n

Sous le capot : comment Go voit l'enum

\n\n

Voyons ce qui se passe réellement lors de la compilation.

\n\n

1. iota n'est pas du runtime

\n\n

iota n'existe pas pendant l'exécution du programme. C'est un outil de préprocesseur (plus précisément, une partie du compilateur de paquets). Lors de la compilation, tous les iota sont remplacés par des nombres concrets. Dans le binaire résultant, vous verrez simplement 0, 1, 2.

\n\n

Vous pouvez le vérifier avec go tool compile ou simplement en regardant le code assembleur :

\n\n
// Code source\nconst (\n    A                

Blogs

Book Recommendations