Esse post faz parte de uma série onde pretendo compartilhar o básico essencial para desenvolver com GoLang.
No primeiro post, sobre variáveis, eu mencionei que sistemas funcionam com entrada -> processamento -> saída. Nesse post vamos entender isso um pouco melhor.
Algoritmos
Toda tarefa executada por um computador é resultado de um algoritmo. Uma definição simples de entender é de que algoritmos são receitas com o passo a passo do que o computador deve fazer.
Diferente de uma receita de comida, para o computador você precisa dar todos os detalhes.
Etapas de um algoritmo
Todo algoritmo pode ser dividido em algumas etapas simples:
- entrada: leitura de dados que são armazenados em variáveis.
- sequência: ordem em que as etapas devem acontecer.
- condições: controle de fluxo 👀
- repetições: controle de fluxo 👀
- saída: a resposta do problema que o algoritmo está resolvendo.
Não parece tão complicado, não é? Entendendo essas etapas você consegue entender qualquer software, não importa a linguagem, paradigma ou framework. Todos funcionam dessa maneira.
A parte boa, você provavelmente já está fera em entrada
pois leu o post sobre variáveis. A parte de sequência é bem auto explicativa e vai ficar bem fácil de visualizar com um exemplo. Então vamos ao que interessa, controles de fluxos em Go.
Controle de Fluxo
Condições IF, ELSE, SWITCH
Condições com IF em go são muito parecidas com a do C e suas similares, tendo alguns detalhes.
if condicao {
fmt.Println("faz algo genial")
}
Temos 3 coisas:
- o uso da palavra reservada
if
. - uma condição (sem parênteses) podendo ser uma variável booleana ou uma expressão lógica.
- bloco dentro de chaves
{...}
, que em Go é obrigatório.
// você também pode utilizar else...if
if condicao {
fmt.Println("faz algo genial")
} else if outra_condicao {
fmt.Println("faz algo genial ao contrario")
} else {
fmt.Println("desiste")
}
Expressão lógica
Se esse é um dos seus primeiros contatos com programação, esse material provavelmente não será o suficiente, mas eu espero que possa ser um incentivo para que você busque mais conhecimento, disclaimer feito. Vamos lá.
Expressões lógicas podem ter operadores de comparação
e/ou operadores lógicos
.
Operadores de comparação
== igual
!= diferente
< menor
<= menor ou igual
> maior
>= maior ou igual
Operadores lógicos
&& conjunção (AND)
|| disjunção (OR)
! negação
Exemplo simples
// utilizando operador de comparação + operador lógico
if produto.status == publicado && produto.cor != azul {
fmt.Println("Produto selecionado")
}
E é basicamente dessa forma que programamos tomadas de decisões dentro do código. Mais uma vez, se esse é um dos seus primeiros contatos eu vou te sugerir o seguinte, da uma olhada em:
Álgebra Booleana
Tabela Verdade
Não se assuste pelos nomes, são tópicos que você precisa exercitar e se tiver oportunidade faça um curso de lógica de programação.
SWITCH
Switch em Go são bastante flexiveis, podendo ser usados de algumas maneiras, a maneira mais comum é criar condições para conjunto de tipos, novamente usando nosso produto como exemplo:
// bastante comum de ser usado com tipos enumerados
switch produto.cor {
case vermelho:
fmt.Println("Desconto 20% no vermelho")
case verde:
fmt.Println("Desconto 10% no verde")
case azul:
fmt.Println("Desconto 5% no azul")
}
Outra sintaxe possível e também incentivada é utilizar o switch vazio e os cases com expressões lógicas, é uma maneira idiomática de evitar series grandes de if..else..if:
switch {
case meuStatus != rascunho && meuStatus != deletado:
fmt.Println("Faz algo com produtos diferentes de rascunhos")
case meuStatus == publicado || meuStatus != congelado:
fmt.Println("Faz algo com publicados")
case meuStatus == congelado:
fmt.Println("Faz algo com congelados")
}
Para mais detalhes veja a documentação:
Switch_statements
Effective Go Switch
Repetições For
Em Go a única palavra reservada para laços de repetições é o for
.
Vamos a alguns exemplos rápidos:
// loop infinito
for {
fmt.Println("rodando... pra sempre")
time.Sleep(time.Second * 1)
}
// repete enquanto a condição for verdadeira
for meuStatus != publicado {
fmt.Println("rodando... pra sempre")
time.Sleep(time.Second * 1)
//... faz algum processamento que atualize meuStatus
}
// for incremental
// além a condição tem operação de inicialização: i := 0
// e uma pós operação para incrementar a variável
for i := 0; i < 10; i++ {
fmt.Println(i)
}
Palavra reservada range
Além dos exemplos acima, quando estiver iterando com slices e maps, é possível utilizar range
para ambos:
personagens := []string{"Kurono", "Guts", "Eren"}
// range te devolve duas variáveis, o índice e o valor
for i, valor := range personagens {
fmt.Println(i, valor)
}
Exatamente a mesma sintaxe para maps
personagemAnime := map[string]string{
"Eren": "Attack on Titan",
"Guts": "Berserk",
"Kurono": "Gantz",
}
for chave, valor := range personagemAnime {
fmt.Println(chave, valor)
}
Um detalhe importante, nem sempre queremos trabalhar com o índice do array ou a chave do mapa, é bem comum a gente só iterar pelos valores, nesse caso precisamos usar o caracter _
:
personagens := []string{"Kurono", "Guts", "Eren"}
for _, valor := range personagens {
fmt.Println(valor)
}
Resumo
Nesse post você viu como fazer o controle de fluxo de um código em Go e a estrutura de um algoritmo. E por mais que possa soar exagerado, é sério que isso pode te tornar capaz de ler qualquer código.
Mas veja, para fazermos uma analogia, é como se eu tivesse te apresentado as notas musicais em um instrumento especifico. Você agora é capaz de ler partituras e com exercício pode começar a tocar sua versão.
- algoritmos são receitas
- etapas de um algoritmo: entrada, sequência, condições, repetições, saída
- estude mais sobre expressões lógicas
- estude tabela verdade e algebra booleana