Ablaufsteuerung mit switch-Anweisungen

Abgeschlossen

Wie andere Programmiersprachen unterstützt Go switch-Anweisungen. Verwenden Sie switch-Anweisungen, um die Verkettung mehrerer if-Anweisungen zu vermeiden. Mithilfe von switch-Anweisungen vermeiden Sie die Schwierigkeit, Code zu verwalten und zu lesen, der viele if-Anweisungen enthält. Diese Anweisungen vereinfachen auch die Erstellung komplizierter Bedingungen. Betrachten Sie die switch-Anweisungen in den folgenden Abschnitten.

Einfache switch-Syntax

Wie bei der if-Anweisung sind für die switch-Bedingung keine Klammern erforderlich. In ihrer einfachsten Form sieht eine switch-Anweisung wie folgt aus:

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")
}

Wenn Sie den vorangehenden Code mehrmals ausführen, werden Sie jedes Mal eine andere Ausgabe erhalten. (Aber wenn Sie den Code in Go Playground ausführen, erhalten Sie jedes Mal dasselbe Ergebnis. Das ist eine der Einschränkungen des Diensts.)

Go vergleicht jeden Fall der switch-Anweisung, bis es eine Übereinstimmung für die Bedingung findet. Beachten Sie jedoch, dass der vorstehende Code nicht alle möglichen Fälle von num-Variablenwerten abdeckt. Wenn num am Ende 5 ist, lautet die Programmausgabe ok.

Alternativ können Sie den Standardanwendungsfall genauer angeben und ihn wie folgt einfügen:

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

Beachten Sie, dass Sie für den default-Fall keinen überprüfenden Ausdruck schreiben. Der Wert der i-Variablen wird anhand der case-Anweisungen überprüft, und der default-Fall behandelt alle nicht überprüften Werte.

Verwenden mehrerer Ausdrücke

Gelegentlich stimmen mehrere Ausdrücke nur mit einer case-Anweisung überein. Wenn Sie in Go eine case-Anweisung verwenden möchten, um mehr als einen Ausdruck einzubeziehen, trennen Sie die Ausdrücke durch Kommas (,). Dieses Verfahren ermöglicht es Ihnen, doppelten Code zu vermeiden.

Das folgende Codebeispiel zeigt, wie Sie mehrere Ausdrücke einbeziehen können.

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)
}

Beachten Sie, dass die Werte, die Sie in die Ausdrücke für die case-Anweisung einbeziehen, dem Datentyp der Variablen entsprechen, die die switch-Anweisung überprüft. Wenn Sie einen ganzzahligen Wert als neue case-Anweisung angeben, wird das Programm nicht kompiliert.

Aufrufen einer Funktion

Ein switch kann auch eine Funktion aufrufen. Über diese Funktion können Sie case-Anweisungen für mögliche Rückgabewerte schreiben. Der folgende Code ruft z. B. die Funktion time.Now() auf. Die von ihr ausgegebene Ausgabe hängt vom aktuellen Wochentag ab.

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())
}

Wenn Sie eine Funktion über eine switch-Anweisung aufrufen, können Sie ihre Logik ändern, ohne den Ausdruck zu ändern, da Sie immer überprüfen, was von der Funktion zurückgegeben wird.

Außerdem können Sie eine Funktion über eine case-Anweisung aufrufen. Verwenden Sie das Verfahren z. B., um ein bestimmtes Muster mithilfe eines regulären Ausdrucks zu vergleichen. Hier sehen Sie ein Beispiel:

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")
    }
}

Beachten Sie, dass der switch-Block keinen überprüfenden Ausdruck aufweist. Dieses Konzept wird im nächsten Abschnitt erläutert.

Auslassen einer Bedingung

In Go können Sie eine Bedingung in einer switch-Anweisung wie in einer if-Anweisung auslassen. Dieses Muster ist wie der Vergleich eines true-Werts, als ob Sie erzwingen würden, dass die switch-Anweisung die ganze Zeit ausgeführt wird.

Hier ist ein Beispiel, wie Sie eine switch-Anweisung ohne Bedingung schreiben können:

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")
    }
}

Das Programm führt immer diesen Typ switch-Anweisungen aus, weil die Bedingung immer erfüllt ist. Ein bedingter switch-Block ist möglicherweise einfacher zu verwalten als eine lange Kette von if- und else if-Anweisungen.

Wechsel der Logik zum nächsten Fall

In einigen Programmiersprachen schreiben Sie am Ende jeder case-Anweisung ein break-Schlüsselwort. Wenn die Logik in Go jedoch einen Fall ergibt, verlässt sie den switch-Block, sofern Sie sie nicht explizit beenden. Verwenden Sie das Schlüsselwort fallthrough, damit die Logik zum nächsten unmittelbaren Fall wechselt.

Betrachten Sie zum besseren Verständnis dieses Musters das folgende Codebeispiel.

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)
    }
}

Führen Sie den Code aus, und analysieren Sie die Ausgabe:

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

Sehen Sie einen Fehler?

Beachten Sie, dass es dem ersten Fall entspricht, da num den Wert 15 (weniger als 50) ergibt. Aber num ist nicht größer als 100. Und da die erste case-Anweisung ein fallthrough-Schlüsselwort aufweist, wechselt die Logik ohne Überprüfung des Falls sofort zur nächsten case-Anweisung. Daher müssen Sie vorsichtig vorgehen, wenn Sie das Schlüsselwort fallthrough verwenden. Möglicherweise ist das Verhalten, das dieser Code erstellt, nicht erwünscht.