No artigo anterior vimos sobre variáveis e constantes na Golang, agora nós vamos aprender quais são e como utilizar as estruturas condicionais e de repetição disponíveis na linguagem Go.
As estruturas condicionais estão diretamente ligadas ao processo de tomada de decisão dentro de um algoritmo, são elas que nos permitem alterar o fluxo de execução do código dependendo dos valores com os quais estamos trabalhando.
Já as estruturas de repetição, assim como o nome já diz, nos permitem repetir certos trechos de códigos um número determinado ou indeterminado de vezes, dependendo sempre de qual a condição de parada para tal estrutura.
Tanto as estruturas de repetição quanto as estruturas de condição irão trabalhar na sua maioria das vezes com valores booleanos, ou seja, true
(verdadeiro) e false
(falso). Caso você ainda não esteja familiarizado com os conceitos de estruturas condicionais e de repetição na lógica de programação, recomendo a leitura do artigo Estruturas condicionais e de repetição, que temos aqui no blog da TreinaWeb.
Estruturas condicionais
As estruturas condicionais possibilitam ao programa tomar decisões e alterar o seu fluxo de execução. Isso possibilita ao desenvolvedor o poder de controlar quais são as tarefas e trechos de códigos executados de acordo com diferentes situações.
As estruturas condicionais geralmente analisam expressões booleanas e, caso estas expressões sejam verdadeiras, um trecho do código é executado. No caso contrário, outro trecho do código é executado.
Estrutura if/else
O if/else é uma estrutura de condição em que uma expressão booleana é analisada. Quando a condição que estiver dentro do if
for verdadeira, ela é executada. Já o else
é utilizado para definir o que é executado quando a condição analisada pelo if
for falsa. Caso o if
seja verdadeiro e, consequentemente, executado, o else
não é executado.
O if
pode ser utilizado em conjunto com o else
ou até mesmo sozinho, caso necessário.
Abaixo, temos um exemplo onde o if
é utilizado em conjunto com o else
.
package main
import "fmt"
func main() {
idade := 18
if idade >= 18 {
// Se a váriavel idade for maior ou igual à 18 esse trecho de código será executado
fmt.Println("Você é maior de idade!")
} else {
// Se a váriavel idade não for maior ou igual à 18 esse trecho de código será executado
fmt.Println("Você é menor de idade!")
}
}
Também podemos utilizar somente o if
, não definindo um fluxo alternativo.
package main
import "fmt"
func main() {
idade := 18
if idade >= 18 {
// Se a váriavel idade for maior ou igual à 18 esse trecho de código será executado
fmt.Println("Você é maior de idade!")
}
// Se a váriavel idade não for maior ou igual à 18, nenhuma frase será exibida
}
Ainda é possível encadear múltiplas estruturas if/else
caso necessário.
package main
import "fmt"
func main() {
idade := 18
if idade >= 18 {
// Se a váriavel idade for maior ou igual à 18 esse trecho de código será executado
fmt.Println("Você é maior de idade!")
} else if idade >= 16 {
// Se a váriavel idade não for maior ou igual à 18 mas for maior ou igual a 16 esse trecho de código será executado
fmt.Println("Você não é maior de idade, mas já pode votar!")
} else {
// Se a váriavel idade não for maior ou igual à 18 esse trecho de código será executado
fmt.Println("Você é menor de idade!")
}
}
Estrutura switch/case
A estrutura condicional switch/case vem como alternativa, em momentos, em que temos que utilizar múltiplos if's
no código. Múltiplos if/else
encadeados tendem a tornar o código muito extenso, pouco legível e com baixo índice de manutenção.
O switch/case
testa o valor contido em uma variável, realizando uma comparação com cada uma das opções. Cada uma dessas possíveis opções é delimitada pela instrução case
.
Podemos ter quantos casos de análise forem necessários e, quando um dos valores corresponder ao da variável, o código do case
correspondente será executado. Caso a variável não corresponda a nenhum dos casos testados, o último bloco será executado, chamado de default
(padrão).
package main
import "fmt"
func main() {
mes := 1
switch mes {
case 1:
fmt.Println("O mês é Janeiro!")
case 2:
fmt.Println("O mês é Fevereiro")
case 3:
fmt.Println("O mês é Março")
case 4:
fmt.Println("O mês é Abril")
case 5:
fmt.Println("O mês é Maio")
case 6:
fmt.Println("O mês é Junho")
case 7:
fmt.Println("O mês é Julho")
case 8:
fmt.Println("O mês é Agosto")
case 9:
fmt.Println("O mês é Setembro")
case 10:
fmt.Println("O mês é Outubro")
case 11:
fmt.Println("O mês é Novembro")
case 12:
fmt.Println("O mês é Dezembro")
default:
fmt.Println("Mês inválido")
}
}
Na maioria das linguagens que possuem a estrutura switch/case
, é necessário colocar a instrução break
ao final de cada cláusula case
, mas na linguagem Go, isso não é necessário.
Estruturas de repetição
Estruturas de repetição, também conhecidas como loops (laços), são utilizadas para executar repetidamente uma instrução ou bloco de instrução enquanto determinada condição estiver sendo satisfeita.
Na linguagem Go temos apenas uma estrutura de repetição, sendo a estrutura for
, porém ela pode ser executada de maneiras diferentes, assim, tendo comportamentos diferentes.
Estrutura for com condição simples
O for com condição simples é uma estrutura de repetição que irá repetir o bloco de código enquanto uma determinada condição for verdadeira, geralmente utilizamos essa estrutura quando não sabemos quantas vezes o trecho de código em questão deve ser repetido.
Essa estrutura possui a seguinte sintaxe:
for <condição> {
// Trecho de código a ser repetido
}
Abaixo, temos um exemplo do for
com condição simples. Neste exemplo, é pedido ao usuário que tente adivinhar o número. Enquanto o usuário não acerta o número, é pedido para que o usuário digite o valor que ele acha que é o correto. Perceba que nós temos um trecho de código que é sempre repetido, o pedido do número para o usuário. Mas, não sabemos exatamente quando o usuário vai acertar este número, ou seja, não sabemos exatamente quantas vezes o trecho de código será repetido. Nessa situação, o for
com condição simples é a estrutura de repetição mais adequada.
package main
import "fmt"
func main() {
numero := -1
for numero != 10 {
fmt.Print("Digite um número: ")
fmt.Scanln(&numero)
if numero < 10 {
fmt.Println("Você errou, tente um número maior")
} else if numero > 10 {
fmt.Println("Você errou, tente um número menor")
} else {
fmt.Println("Você acertou")
}
}
}
Estrutura for clássica
O for clássico é uma estrutura de repetição que trabalha com uma variável de controle e que repete o seu bloco de código até que uma determinada condição que envolve essa variável de controle seja falsa, geralmente utilizamos essa estrutura for
quando sabemos a quantidade de vezes que o laço precisará ser executado.
O for
clássico possui a seguinte sintaxe:
for <variável de controle>; <condição de parada>; <incremento/decremento da váriavel de controle> {
// Trecho de código a ser repetido
}
Quando utilizamos o for
clássico, precisamos de uma variável para auxiliar a controlar a quantidade de repetições a serem executadas. Essa variável é chamada de variável de controle, declarada no primeiro argumento do for
.
O segundo argumento do for
clássico é utilizado para definir até quando o for
será executado. Geralmente, trata-se de uma condição booleana em cima da variável de controle.
O terceiro argumento indica o quanto a variável de controle será modificada no final de cada execução dentro do for
clássico.
Veja o exemplo abaixo:
package main
import "fmt"
func main() {
for i := 1; i <= 10; i++ {
fmt.Println("A váriavel i agora é:", i)
}
}
A execução desse código causará a seguinte saída:
A váriavel i agora é: 1
A váriavel i agora é: 2
A váriavel i agora é: 3
A váriavel i agora é: 4
A váriavel i agora é: 5
A váriavel i agora é: 6
A váriavel i agora é: 7
A váriavel i agora é: 8
A váriavel i agora é: 9
A váriavel i agora é: 10
Isso acontece porque:
- A variável de controle, que chamamos de
i
, tem como valor inicial1
; - No segundo argumento, onde escrevemos
i <= 10
, estamos dizendo que o bloco de código dofor
será executado enquanto o valor dei
for menor ou igual a10
; - O terceiro argumento foi definido como
i++
, estamos dizendo que, no fim de cada execução dofor
, o valor dei
será incrementado em1
. Isso quer dizer que, no fim da primeira execução,i
irá de 1 para 2, na segunda execução, irá de 2 para 3, e assim por diante; - Com isso, o bloco de código do
for
será executado por 10 vezes, já que oi
é iniciado em1
. A saída do código acima mostra que a mensagem foi escrita por 10 vezes, onde oi
variou de 1 até 10.
Estrutura for sem condição
Também é possível utilizar a estrutura for sem passar nenhuma condição, utilizamos essa forma quando queremos criar um laço de repetição infinito.
Para essa estrutura utilizamos a seguinte sintaxe:
for {
// Trecho de código a ser repetido
}
A primeiro momento parece ser estranho querer criar um laço de repetição infinito, mas em alguns casos isso é útil, por exemplo, podemos criar um programa que vai ficar executando por tempo indeterminado e que constantemente vai tentar ler informações de algum local, como um arquivo ou um sistema de filas.
Estrutura for com range
É muito comum as linguagens de programação possuírem uma estrutura de repetição chamada de foreach, basicamente a estrutura foreach
serve para podermos percorrer os elementos de uma estrutura de dados de forma mais simples e menos verbosa.
Na Golang nós não temos essa estrutura, mas é possível termos o mesmo comportamento utilizando a palavra reservada range. O range
permite iterar sobre os elementos de diferentes estruturas de dados.
Veja como percorríamos um array com um for
clássico:
package main
import "fmt"
func main() {
alunos := []string{"Cleyson", "Anna", "Autobele", "Hayssa"}
for i := 0; i < 4; i++ {
fmt.Println(alunos[i])
}
}
No código acima foi criado um array de strings com quatro posições, em cada uma dessas tem o nome de um aluno, logo em seguida temos um for
que irá fazer com que a variável controladora i
vá de 0 a 3 e então utilizamos a variável i
para fazer acesso aos elementos do array pelo índice e assim conseguir imprimir todos os seus valores.
O problema do uso do for
clássico para essa tarefa é que não nos interessa o índice do array propriamente dito e sim apenas os seus valores internos, então podemos utilizar a estrutura for
com o range
para termos um código mais limpo.
Veja como ficaria o código acima refatorado para usarmos o for
com range
:
package main
import "fmt"
func main() {
alunos := []string{"Cleyson", "Anna", "Autobele", "Hayssa"}
for _, aluno := range alunos {
fmt.Println(aluno)
}
}
Basicamente o range
vai permitir que possamos iterar sobre os elementos de uma estrutura de dados com o auxílio do for
, outro ponto interessante é que o range
retorna dois valores, sendo o primeiro o índice da estrutura de dados e o segundo o próprio elemento.
Como no exemplo acima só nos interessava o elemento e não o seu índice, o primeiro valor foi ignorado utilizando o caractere _
(underscore).
Em ambos os casos o resultado impresso no terminal será:
Cleyson
Anna
Autobele
Hayssa
Conclusão
Como vimos nesse artigo a Golang possui todas as estruturas de condição e de repetição básicas que existem na maioria das linguagens de programação, vimos quais são essas estruturas e como podemos utilizá-las em nossos programas.
Por fim, caso queira aprender mais sobre a Go e sua infinidade de recursos saiba que aqui na TreinaWeb temos o curso Go Básico que possui 05h30 de vídeo e um total de 37 exercícios.
Veja quais são os tópicos abordados durante o curso Go Básico:
- Compreender a sintaxe básica da Golang;
- Compreender conceitos básicos envolvidos na Go, como ponteiros de memória;
- Utilizar as estruturas básicas da linguagem, como declaração de variáveis;
- Utilizar as principais estruturas de conjuntos da Go, como arrays, slices e maps;
- Entender as principais funções built-in, como make(), new(), panic(), recover() e defer;
- Organizar o código em pacotes e utilizar os principais pacotes disponibilizados pela linguagem;
- Entender como podemos utilizar concorrência com a Golang, inclusive com técnicas como os channels;
- Entender o que são as structs na Go e como podemos utilizar um pouco de orientação a objetos com a linguagem;
- Realizar operações de I/O no sistema operacional, como a criação e escrita de arquivos.