Fluxo de controle com instruções de interruptor
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.