Break en Go : casse-t-il switch et select ? Comparaison des approches

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

Break, ce casse-tête : comment Go a bouleversé la « règle du switch » habituelle

\n\n

Si vous avez déjà codé en C, C++, Java ou JavaScript, vous connaissez le rituel : après chaque case dans un switch, il faut impérativement ajouter un break. Sinon, bienvenue en enfer du « fall-through », où le code s'exécute d'un case à l'autre jusqu'à rencontrer un break ou la fin de la structure.

\n\n

Imaginez maintenant : vous passez à Go, vous écrivez un switch et, par habitude, vous insérez un break à la fin de chaque case. Le code fonctionne. Mais vous vous demandez : « Est-ce vraiment nécessaire ? Et que se passe-t-il si je l'enlève ? »

\n\n

Cette question est l'une des plus populaires sur Stack Overflow dans la section Go. Et la réponse surprend les débutants : en Go, le break dans switch et select n'est pas obligatoire, mais il existe et fait quelque chose de différent. Décortiquons cela avec des exemples pour que vous ne soyez plus jamais perdu.

\n\n

Go vs. C : un switch « inversé »

\n\n

Dans les langages classiques de type C, le switch fonctionne ainsi :

\n\n
// Pseudo-code C\nint x = 2;\nswitch(x) {\n    case 1:\n        printf("Un");\n        break;  // Sans break, on passe au case suivant\n    case 2:\n        printf("Deux");\n        break;\n    default:\n        printf("Autre");\n}\n// Sortie : "Deux"
\n\n

Retirez le break après case 1 et le programme affichera « UnDeux ». Ce comportement s'appelle le fall-through, et il est souvent source de bugs.

\n\n

En Go, ils ont décidé : « Assez de ça ! » Par défaut, chaque case dans un switch se termine automatiquement, et break n'est pas nécessaire :

\n\n
package main\n\nimport "fmt"\n\nfunc main() {\n    x := 2\n    switch x {\n    case 1:\n        fmt.Println("Un")\n        // break inutile — on sort du switch\n    case 2:\n        fmt.Println("Deux")\n        // break inutile\n    default:\n        fmt.Println("Autre")\n    }\n    // Sortie : "Deux"\n}
\n\n

Mais si vous mettez quand même un break, rien de grave : le code quitte simplement le switch plus tôt. Cependant, pourquoi ajouter un break superflu alors que c'est le comportement par défaut ?

\n\n

Et le fall-through alors ?

\n\n

Si vous avez besoin de « tomber » dans le case suivant, Go propose un mot-clé explicite : fallthrough :

\n\n
switch x {\ncase 1:\n    fmt.Println("Un")\n    fallthrough  // On dit clairement : « Je veux passer au case suivant »\ncase 2:\n    fmt.Println("Deux")\ndefault:\n    fmt.Println("Autre")\n}\n// Avec x=1, affichera : "Un" et "Deux"
\n\n

Notez que fallthrough ne fonctionne que pour le case suivant et non en chaîne. Cela a été conçu spécifiquement pour éviter les erreurs accidentelles.

\n\n

Select : le « frère » multicanal de switch

\n\n

Go possède une structure unique : select. Elle ressemble à switch, mais ne fonctionne qu'avec les canaux. Et ici aussi, break existe, mais avec une subtilité.

\n\n
package main\n\nimport (\n    "fmt"\n    "time"\n)\n\nfunc main() {\n    ch1 := make(chan string)\n    ch2 := make(chan string)\n\n    go func() {\n        time.Sleep(1 * time.Second)\n        ch1 <- "Bonjour du canal 1"\n    }()\n    go func() {\n        time.Sleep(2 * time.Second)\n        ch2 <- "Bonjour du canal 2"\n    }()\n\n    select {\n    case msg1 := <-ch1:\n        fmt.Println(msg1)\n        break  // Sortie du select\n    case msg2 := <-ch2:\n        fmt.Println(msg2)\n        break  // Sortie du select\n    case <-time.After(3 * time.Second):\n        fmt.Println("Timeout")\n    }\n}
\n\n

Ici, break n'est pas non plus obligatoire — le select se termine après l'exécution d'un seul case. Mais à quoi sert-il alors ? La réponse : à sortir d'une boucle externe !

\n\n

La « particularité » principale de break

Blogs

Book Recommendations