As instruções condicionais dão aos programadores capacidade para direcionar seus programas a tomarem algumas medidas se uma condição for verdadeira e outra ação se a condição for falsa. Frequentemente, queremos comparar algumas variáveis com vários valores possíveis, tomando diferentes ações em cada circunstância. É possível fazer isso funcionar usando somente as instruções if
. No entanto, escrever um software não diz respeito somente a fazer as coisas funcionarem, mas também de comunicar sua intenção para outros desenvolvedores e para si mesmo no futuro. O switch
é uma instrução condicional alternativa útil para comunicar as ações tomadas pelos seus programas em Go quando diante de diferentes opções.
Tudo o que podemos escrever com a instrução switch também pode ser escrito com as instruções if
. Neste tutorial, vamos examinar alguns exemplos do que a instrução switch pode fazer, quais instruções if
ela substitui e onde ela é mais adequadamente aplicada.
A instrução switch é geralmente usada para descrever as ações tomadas por um programa quando atribuímos valores específicos para uma variável. O exemplo a seguir demonstra como realizaríamos isso usando instruções if
:
package main
import "fmt"
func main() {
flavors := []string{"chocolate", "vanilla", "strawberry", "banana"}
for _, flav := range flavors {
if flav == "strawberry" {
fmt.Println(flav, "is my favorite!")
continue
}
if flav == "vanilla" {
fmt.Println(flav, "is great!")
continue
}
if flav == "chocolate" {
fmt.Println(flav, "is great!")
continue
}
fmt.Println("I've never tried", flav, "before")
}
}
Isso gerará o seguinte resultado:
Outputchocolate is great!
vanilla is great!
strawberry is my favorite!
I've never tried banana before
Dentro de main
, definimos uma fatia com sabores de sorvete. Na sequência, usamos um for loop
para iterar por eles. Usamos três instruções if
para imprimir diferentes mensagens que indicam preferências por diferentes sabores de sorvete. Cada instrução if
deve usar a instrução continue
para parar a execução do loop for
, de modo que a mensagem padrão no final não seja impressa em relação aos sabores preferidos de sorvete.
À medida que adicionamos novas preferências de sorvete, temos que continuar adicionando instruções if
para lidar com os novos casos. As mensagens duplicadas, como no caso de "vanilla"
e "chocolate"
, devem ter instruções if
duplicadas. Para futuros leitores do nosso código (nós mesmos, inclusive), a natureza repetitiva das instruções if
atrapalha o entendimento sobre parte importante do que elas estão fazendo — comparando a variável com vários valores e tomando diferentes ações. Além disso, nossa mensagem de fallback fica separada das condicionais, fazendo-a parecer não relacionada. A instrução switch
pode nos ajudar a organizar essa lógica melhor.
A instrução switch
começa com a palavra-chave switch
e é seguida, em sua forma mais básica, de algumas variáveis com as quais serão feitas comparações. Após a instrução vem um par de chaves ({}
) onde várias cláusulas de caso podem aparecer. As cláusulas de caso descrevem as medidas que o seu programa em Go deve adotar quando a variável informada à instrução switch for igual ao valor referenciado pela cláusula de caso. O exemplo a seguir converte o exemplo anterior para que use uma switch
em vez de várias instruções if
:
package main
import "fmt"
func main() {
flavors := []string{"chocolate", "vanilla", "strawberry", "banana"}
for _, flav := range flavors {
switch flav {
case "strawberry":
fmt.Println(flav, "is my favorite!")
case "vanilla", "chocolate":
fmt.Println(flav, "is great!")
default:
fmt.Println("I've never tried", flav, "before")
}
}
}
O resultado é o mesmo de antes:
Outputchocolate is great!
vanilla is great!
strawberry is my favorite!
I've never tried banana before
Mais uma vez, definimos uma fatia com sabores de sorvete em main
e usamos a instrução range
para iterar sobre cada sabor. Dessa vez, no entanto, usamos uma instrução switch
que irá examinar a variável flav
. Usamos duas cláusulas case
para indicar as preferências. Já não precisamos de instruções continue
, já que apenas uma cláusula case
será executada pela instrução switch
. Também podemos combinar a lógica duplicada das condicionais "chocolate"
e "vanilla"
, separando cada uma com uma vírgula na declaração da cláusula case
. A cláusula default
serve como nossa cláusula catch-all [global]. Ela executará em relação a todos os sabores que ainda não foram contabilizados no corpo da instrução switch
. Nesse caso, "banana"
fará com que default
seja executada, imprimindo a mensagem I've never tried banana before
(Nunca experimentei o de banana antes).
Essa forma simplificada de instruções switch
lida com o uso mais comum dado a elas: comparar uma variável com várias alternativas. Ela também nos traz conveniência nos locais em que queremos tomar a mesma medida em relação a diversos valores diferentes e algumas outras medidas quando nenhuma das condições listadas forem atendidas pelo uso da palavra-chave default
informada.
Quando essa forma simplificada da switch
mostra-se limitada, podemos usar uma forma mais geral da instrução switch
.
As instruções switch
são úteis para agrupar coleções de condicionais mais complicadas, mostrando que elas estão de alguma maneira relacionadas. Isso é mais comumente usado ao comparar algumas variáveis com uma gama de valores, em vez de valores específicos, como no exemplo anterior. O exemplo a seguir implementa um jogo de adivinhação usando instruções if
que poderia ser beneficiado por uma instrução switch
:
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
rand.Seed(time.Now().UnixNano())
target := rand.Intn(100)
for {
var guess int
fmt.Print("Enter a guess: ")
_, err := fmt.Scanf("%d", &guess)
if err != nil {
fmt.Println("Invalid guess: err:", err)
continue
}
if guess > target {
fmt.Println("Too high!")
continue
}
if guess < target {
fmt.Println("Too low!")
continue
}
fmt.Println("You win!")
break
}
}
O resultado variará dependendo do número aleatório selecionado e do quão bem você jogar o jogo. Aqui está o resultado de uma sessão para exemplificar:
OutputEnter a guess: 10
Too low!
Enter a guess: 15
Too low!
Enter a guess: 18
Too high!
Enter a guess: 17
You win!
Nosso jogo de adivinhação precisa de um número aleatório contra o qual fazer as comparações. Portanto, usamos a função rand.Intn
do pacote math/rand
. Para garantir que obteremos diferentes valores para target
toda vez que jogarmos o jogo, usamos o rand.Seed
para aplicar um fator de aleatoriedade ao gerador de números aleatórios, com base no momento atual. O argumento 100
para rand.Intn
nos dará um número no intervalo de 0-100. Então, usamos um loop for
para começar a coletar adivinhações do jogador.
A função fmt.Scanf
nos oferece um meio para ler a entrada do usuário em uma variável de nossa escolha. Ela usa um verbo para a string de formato, a qual converte a entrada do usuário para o tipo que esperamos. O %d
aqui significa que esperamos um int
e enviamos o endereço da variável guess
para que o fmt.Scanf
consiga definir tal variável. Após lidar com quaisquer erros de análise, usamos duas instruções if
para comparar a adivinhação do usuário com o valor target
. A string
que elas retornam, junto com o bool
[booleano], controla a mensagem exibida para o jogador e também se o jogo fechará.
Essas instruções if
tornam vago o fato de que o intervalo de valores com o qual a variável está sendo comparada são todos relacionados de alguma maneira. À primeira vista, pode ser difícil dizer se perdemos alguma parte do intervalo. O exemplo a seguir refatora o exemplo anterior para usar uma instrução switch
como alternativa:
package main
import (
"fmt"
"math/rand"
)
func main() {
target := rand.Intn(100)
for {
var guess int
fmt.Print("Enter a guess: ")
_, err := fmt.Scanf("%d", &guess)
if err != nil {
fmt.Println("Invalid guess: err:", err)
continue
}
switch {
case guess > target:
fmt.Println("Too high!")
case guess < target:
fmt.Println("Too low!")
default:
fmt.Println("You win!")
return
}
}
}
Isso gerará um resultado similar ao seguinte:
OutputEnter a guess: 25
Too low!
Enter a guess: 28
Too high!
Enter a guess: 27
You win!
Nessa versão do jogo de adivinhação, substituímos o bloco de instruções if
por uma instrução switch
. Omitimos o argumento da expressão para switch
porque somente estamos interessados em usar a instrução switch
para coletar condicionais juntas. Cada cláusula case
contém uma expressão diferente que compara o guess
com o target
. De maneira similar à primeira vez que substituímos instruções if
pela switch
, já não precisamos mais de instruções continue
, já que apenas uma cláusula case
será executada. Por fim, a cláusula default
lida com o caso onde o guess == target
, uma vez que cobrimos todos os outros valores possíveis com outras duas cláusulas case
.
Nos exemplos que vimos até agora, será executada exatamente uma instrução case. De vez em quando, você pode desejar combinar os comportamentos das várias cláusulas case
. As instruções switch
fornecem outra palavra-chave para alcançar este comportamento.
As vezes será necessário reutilizar o código que outra cláusula case
contém. Nesses casos, é possível pedir ao Go que execute o corpo da próxima cláusula case
listada usando a palavra-chave fallthrough
. Este próximo exemplo modifica nosso exemplo anterior de sabor de sorvete para refletir com maior precisão nosso entusiasmo por sorvete de morango:
package main
import "fmt"
func main() {
flavors := []string{"chocolate", "vanilla", "strawberry", "banana"}
for _, flav := range flavors {
switch flav {
case "strawberry":
fmt.Println(flav, "is my favorite!")
fallthrough
case "vanilla", "chocolate":
fmt.Println(flav, "is great!")
default:
fmt.Println("I've never tried", flav, "before")
}
}
}
Vamos ver este resultado:
Outputchocolate is great!
vanilla is great!
strawberry is my favorite!
strawberry is great!
I've never tried banana before
Como vimos anteriormente, definimos uma fatia da string
para representar sabores e iterar ao longo dela usando um loop for
. A instrução switch
aqui é idêntica à que já vimos antes, porém com a adição da palavra-chave fallthrough
ao final da cláusula case
para "strawberry"
. Isso faz com que o Go execute o corpo de case "strawberry":
, primeiro imprimindo a string strawberry is my favorite!
(morango é o meu predileto!). Quando encontrar a palavra-chave fallthrough
, executará o corpo da próxima cláusula case
. Isso faz com que o corpo do case "vanilla", "chocolate"
execute, imprimindo strawberry is great!
(morango é uma ótimo!).
A palavra-chave fallthrough
não é usada frequentemente pelos desenvolvedores de Go. Normalmente, a reutilização de código realizada usando a palavra-chave fallthrough
pode ser obtida de maneira melhor definindo-se uma função com o código comum. Por essas razões, o uso da palavra-chave fallthrough
, no geral, é desencorajado.
As instruções switch
nos ajudam a transmitir para outros desenvolvedores que leem nosso código que em um conjunto de comparações, elas estão de alguma maneira relacionadas. Elas facilitarão muito mais quando tivermos que adicionar comportamentos diferentes se um novo caso for adicionado no futuro e possibilitarão a garantia de que tudo o que esquecermos será devidamente tratato apropriadamente com as cláusulas default
. A próxima vez que você se encontrar escrevendo várias instruções if
, sendo que todas envolvem a mesma variável, tente reescrevê-las com uma instrução switch
— será mais fácil revisar o trabalho quando for hora de considerar algum outro valor alternativo.
Se quiser aprender mais sobre a linguagem de programação Go, confira toda a série sobre Como codificar na série Go.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!