Flux de contrôle avec instructions switch

Effectué

Comme les autres langages de programmation, Go prend en charge les instructions switch. Vous pouvez utiliser les instructions switch pour éviter le chaînage de plusieurs instructions if. En utilisant des instructions switch, vous évitez la difficulté de gérer et de lire le code qui comprend de nombreuses instructions if. Ces instructions rendent également les conditions compliquées plus faciles à construire. Examinez les instructions switch dans les sections suivantes.

Syntaxe switch de base

À l’instar de l’instruction if, la condition switch ne requiert pas de parenthèses. Dans sa forme la plus simple, une instruction switch se présente comme suit :

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    sec := time.Now().Unix()
    rand.Seed(sec)
    i := rand.Int31n(10)

    switch i {
    case 0:
        fmt.Print("zero...")
    case 1:
        fmt.Print("one...")
    case 2:
        fmt.Print("two...")
    }

    fmt.Println("ok")
}

Si vous exécutez le code précédent plusieurs fois, vous verrez une sortie différente à chaque fois. (Mais si vous exécutez le code dans le terrain de jeu Go, vous obtenez le même résultat à chaque fois. Ceci est l’une des limitations du service.)

Go compare chaque cas de l’instruction switch jusqu’à ce qu’il trouve une correspondance pour la condition. Toutefois, notez que le code précédent ne couvre pas tous les cas possibles des valeurs de la variable num. Si num finit par être 5, la sortie du programme est ok.

Vous pouvez également être plus précis sur le cas d’usage par défaut et l’inclure comme suit :

switch i {
case 0:
    fmt.Print("zero...")
case 1:
    fmt.Print("one...")
case 2:
    fmt.Print("two...")
default:
    fmt.Print("no match...")
}

Notez que pour le cas default, vous n’écrivez pas d’expression de validation. La valeur de la variable i est validée par rapport aux instructions case et le cas default gère toutes les valeurs non validées.

Utiliser plusieurs expressions

Parfois, plusieurs expressions correspondent à une seule instruction case. Dans Go, si vous souhaitez qu’une instruction case inclue plusieurs expressions, séparez-les par des virgules (,). Cette technique vous permet d’éviter les doublons de code.

L’exemple de code suivant montre comment inclure plusieurs expressions.

package main

import "fmt"

func location(city string) (string, string) {
    var region string
    var continent string
    switch city {
    case "Delhi", "Hyderabad", "Mumbai", "Chennai", "Kochi":
        region, continent = "India", "Asia"
    case "Lafayette", "Louisville", "Boulder":
        region, continent = "Colorado", "USA"
    case "Irvine", "Los Angeles", "San Diego":
        region, continent = "California", "USA"
    default:
        region, continent = "Unknown", "Unknown"
    }
    return region, continent
}
func main() {
    region, continent := location("Irvine")
    fmt.Printf("John works in %s, %s\n", region, continent)
}

Notez que les valeurs que vous incluez dans les expressions de l’instruction case correspondent au type de données de la variable que l’instruction switch valide. Si vous incluez une valeur entière comme nouvelle instruction case, le programme ne sera pas compilé.

Appeler une fonction

Une switch peut également appeler une fonction. À partir de cette fonction, vous pouvez écrire des instructions case pour les valeurs de retour possibles. Par exemple, le code suivant appelle la fonction time.Now(). La sortie imprimée dépend du jour de la semaine.

package main

import (
    "fmt"
    "time"
)

func main() {
    switch time.Now().Weekday().String() {
    case "Monday", "Tuesday", "Wednesday", "Thursday", "Friday":
        fmt.Println("It's time to learn some Go.")
    default:
        fmt.Println("It's the weekend, time to rest!")
    }

    fmt.Println(time.Now().Weekday().String())
}

Quand vous appelez une fonction à partir d’une instruction switch, vous pouvez modifier sa logique sans modifier l’expression, car vous validez toujours ce que la fonction retourne.

Vous pouvez également appeler une fonction à partir d’une instruction case. Utilisez cette technique, par exemple, pour faire correspondre un modèle particulier à l’aide d’une expression régulière. Voici un exemple :

package main

import "fmt"

import "regexp"

func main() {
    var email = regexp.MustCompile(`^[^@]+@[^@.]+\.[^@.]+`)
    var phone = regexp.MustCompile(`^[(]?[0-9][0-9][0-9][). \-]*[0-9][0-9][0-9][.\-]?[0-9][0-9][0-9][0-9]`)

    contact := "foo@bar.com"

    switch {
    case email.MatchString(contact):
        fmt.Println(contact, "is an email")
    case phone.MatchString(contact):
        fmt.Println(contact, "is a phone number")
    default:
        fmt.Println(contact, "is not recognized")
    }
}

Notez que le bloc switch n’a pas d’expression de validation. Nous parlerons de ce concept dans la section suivante.

Omettre une condition

Dans Go, vous pouvez omettre une condition dans une instruction switch comme dans une instruction if. Ce modèle est similaire à la comparaison d’une valeur true comme si vous forciez l’exécution de l’instruction switch en permanence.

Voici un exemple d’écriture d’une instruction switch sans condition :

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    rand.Seed(time.Now().Unix())
    r := rand.Float64()
    switch {
    case r > 0.1:
        fmt.Println("Common case, 90% of the time")
    default:
        fmt.Println("10% of the time")
    }
}

Le programme exécute toujours ce type d’instruction switch, car la condition est toujours true. Un bloc switch conditionnel peut être plus facile à gérer qu’une longue chaîne d’instructions if et else if.

Appliquer la logique au cas suivant

Dans certains langages de programmation, vous devez écrire un mot clé break à la fin de chaque instruction case. Mais dans Go, lorsque la logique se trouve dans un seul cas, elle quitte le bloc switch, sauf si vous l’arrêtez explicitement. Pour que la logique passe au cas immédiat suivant, utilisez le mot clé fallthrough.

Pour mieux comprendre ce modèle, examinez l’exemple de code suivant.

package main

import (
    "fmt"
)

func main() {
    switch num := 15; {
    case num < 50:
        fmt.Printf("%d is less than 50\n", num)
        fallthrough
    case num > 100:
        fmt.Printf("%d is greater than 100\n", num)
        fallthrough
    case num < 200:
        fmt.Printf("%d is less than 200", num)
    }
}

Exécutez le code et analysez la sortie :

15 is less than 50
15 is greater than 100
15 is less than 200

Voyez-vous un problème ?

Notez que, étant donné que la valeur de num est 15 (inférieur à 50), il correspond au premier cas. Mais num n’est pas supérieur à 100. Et étant donné que la première instruction case a un mot clé fallthrough, la logique passe immédiatement à l’instruction case suivante sans valider le cas. Vous devez donc être prudent lorsque vous utilisez le mot clé fallthrough. Vous ne souhaitez peut-être pas obtenir le comportement créé par ce code.