Fluxo de controle com instruções de interruptor

Concluído

Como outras linguagens de programação, Go suporta switch instruções. Você usa switch instruções para evitar encadear várias if instruções. switch Usando instruções, você evita a dificuldade de manter e ler o código que inclui muitas if instruções. Estas declarações também tornam as condições complicadas mais fáceis de construir. Dê uma olhada nas switch declarações nas seções a seguir.

Sintaxe básica do switch

Como a if declaração, a switch condição não requer parênteses. Em sua forma mais simples, uma switch instrução tem esta aparência:

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

Se você executar o código anterior várias vezes, verá uma saída diferente a cada vez. (Mas se você executar o código no Go Playground, obterá o mesmo resultado sempre. Essa é uma das limitações do serviço.)

Go compara cada caso da switch instrução até encontrar uma correspondência para a condição. Mas observe que o código anterior não cobre todos os casos possíveis de valores variáveis num . Se num acabar sendo 5, a saída do programa é ok.

Você também pode ser mais específico sobre o caso de uso padrão e incluí-lo assim:

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

Observe que, para o default caso, você não escreve uma expressão de validação. O valor da i variável é validado em relação às case instruções e o default caso lida com quaisquer valores não validados.

Usar várias expressões

Ocasionalmente, mais de uma expressão corresponde a apenas uma case instrução. Em Ir, se você quiser que uma case instrução inclua mais de uma expressão, separe as expressões usando vírgulas (,). Esta técnica permite evitar códigos duplicados.

O exemplo de código a seguir mostra como incluir várias expressões.

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

Observe que os valores incluídos nas expressões da case instrução correspondem ao tipo de dados da variável que a switch instrução valida. Se você incluir um valor inteiro como uma nova case instrução, o programa não será compilado.

Invocar uma função

A switch também pode invocar uma função. A partir dessa função, você pode escrever case instruções para possíveis valores de retorno. Por exemplo, o código a seguir chama a time.Now() função. A saída que ele imprime depende do dia da semana atual.

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

Quando você chama uma função de uma switch instrução, você pode modificar sua lógica sem alterar a expressão, porque você sempre valida o que a função retorna.

Além disso, você pode chamar uma função a partir de uma case instrução. Use essa técnica, por exemplo, para corresponder a um padrão específico usando uma expressão regular. Eis um exemplo:

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

Observe que o switch bloco não tem expressão de validação. Vamos falar sobre esse conceito na próxima seção.

Omitir uma condição

Em Go, você pode omitir uma condição em uma switch instrução como faz em uma if instrução. Esse padrão é como comparar um true valor como se você estivesse forçando a switch instrução a ser executada o tempo todo.

Aqui está um exemplo de como escrever uma switch declaração sem uma condição:

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

O programa sempre executa esse tipo de switch instrução porque a condição é sempre verdadeira. Um bloqueio condicional switch pode ser mais fácil de manter do que uma longa cadeia de if instruções e else if instruções.

Faça com que a lógica caia para o próximo caso

Em algumas linguagens de programação, você escreve uma break palavra-chave no final de cada case instrução. Mas em Go, quando a lógica cai em um caso, ela sai do bloco, a switch menos que você o pare explicitamente. Para fazer com que a lógica caia para o próximo caso imediato, use a fallthrough palavra-chave.

Para entender melhor esse padrão, veja o exemplo de código a seguir.

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

Execute o código e analise a saída:

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

Vê alguma coisa errada?

Observe que, por num ser 15 (menos de 50), corresponde ao primeiro caso. Mas num não é maior do que 100. E como a primeira case declaração tem uma fallthrough palavra-chave, a lógica vai para a próxima case declaração imediatamente sem validar o caso. Então você tem que ter cuidado quando você usa a fallthrough palavra-chave. Talvez você não queira o comportamento que esse código cria.