Neste terceiro artigo da série “Golang para Iniciantes”, vamos explorar as estruturas de controle de fluxo em Go. Você aprenderá a tomar decisões com if/else, selecionar entre múltiplas opções com switch, e repetir operações com loops for.

Se você está chegando agora, recomendamos começar pela introdução:

📖 ← Artigo Anterior: Sintaxe Básica de Go

If e Else

Go tem uma sintaxe de condicionais limpa e direta.

If Básico

package main

import "fmt"

func main() {
    idade := 18

    if idade >= 18 {
        fmt.Println("Maior de idade")
    }
}

If-Else

package main

import "fmt"

func main() {
    nota := 7.5

    if nota >= 7.0 {
        fmt.Println("Aprovado!")
    } else if nota >= 5.0 {
        fmt.Println("Recuperação")
    } else {
        fmt.Println("Reprovado")
    }
}

If com Inicialização

Uma característica única de Go: você pode inicializar variáveis no if:

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    rand.Seed(time.Now().UnixNano())

    // A variável 'numero' só existe dentro do bloco if
    if numero := rand.Intn(100); numero % 2 == 0 {
        fmt.Printf("%d é par\n", numero)
    } else {
        fmt.Printf("%d é ímpar\n", numero)
    }

    // numero não está acessível aqui!
}

Padrão Idiomático: Error Handling

O if com inicialização é muito usado para tratamento de erros:

package main

import (
    "fmt"
    "strconv"
)

func main() {
    input := "42"

    if numero, err := strconv.Atoi(input); err == nil {
        fmt.Printf("Número: %d\n", numero)
    } else {
        fmt.Printf("Erro: %v\n", err)
    }
}

Switch

O switch em Go é mais flexível que em outras linguagens.

Switch Básico

package main

import "fmt"

func main() {
    dia := 3

    switch dia {
    case 1:
        fmt.Println("Domingo")
    case 2:
        fmt.Println("Segunda")
    case 3:
        fmt.Println("Terça")
    case 4:
        fmt.Println("Quarta")
    case 5:
        fmt.Println("Quinta")
    case 6:
        fmt.Println("Sexta")
    case 7:
        fmt.Println("Sábado")
    default:
        fmt.Println("Dia inválido")
    }
}

Nota: Em Go, você não precisa de break — a execução não “cai” para o próximo case.

Múltiplos Cases

package main

import "fmt"

func main() {
    mes := "janeiro"

    switch mes {
    case "dezembro", "janeiro", "fevereiro":
        fmt.Println("Verão")
    case "março", "abril", "maio":
        fmt.Println("Outono")
    case "junho", "julho", "agosto":
        fmt.Println("Inverno")
    case "setembro", "outubro", "novembro":
        fmt.Println("Primavera")
    }
}

Switch sem Expressão

Funciona como uma série de if-else:

package main

import "fmt"

func main() {
    idade := 25

    switch {
    case idade < 13:
        fmt.Println("Criança")
    case idade < 20:
        fmt.Println("Adolescente")
    case idade < 60:
        fmt.Println("Adulto")
    default:
        fmt.Println("Idoso")
    }
}

Fallthrough

Se você realmente precisa que a execução continue para o próximo case:

package main

import "fmt"

func main() {
    numero := 2

    switch numero {
    case 1:
        fmt.Println("Um")
        fallthrough
    case 2:
        fmt.Println("Dois")
        fallthrough
    case 3:
        fmt.Println("Três")
    }
    // Output: Dois
    //         Três
}

Type Switch

Especialmente útil para trabalhar com interfaces:

package main

import "fmt"

func verificarTipo(i interface{}) {
    switch v := i.(type) {
    case int:
        fmt.Printf("Inteiro: %d\n", v)
    case string:
        fmt.Printf("String: %s\n", v)
    case bool:
        fmt.Printf("Booleano: %t\n", v)
    default:
        fmt.Printf("Tipo desconhecido: %T\n", v)
    }
}

func main() {
    verificarTipo(42)
    verificarTipo("Olá")
    verificarTipo(true)
    verificarTipo(3.14)
}

For: O Único Loop de Go

Go tem apenas uma palavra-chave para loops: for. Mas ela é extremamente versátil.

For Clássico (C-style)

package main

import "fmt"

func main() {
    // Inicialização; condição; pós-operação
    for i := 0; i < 5; i++ {
        fmt.Printf("Iteração %d\n", i)
    }
}

For como While

package main

import "fmt"

func main() {
    contador := 0

    // Apenas a condição
    for contador < 5 {
        fmt.Printf("Contador: %d\n", contador)
        contador++
    }
}

Loop Infinito

package main

import (
    "fmt"
    "time"
)

func main() {
    contador := 0

    // Loop infinito
    for {
        fmt.Printf("Execução %d\n", contador)
        contador++

        if contador >= 5 {
            break  // Sai do loop
        }

        time.Sleep(1 * time.Second)
    }
}

Range

A forma idiomática de iterar sobre coleções:

package main

import "fmt"

func main() {
    // Slice
    frutas := []string{"maçã", "banana", "laranja"}

    // Índice e valor
    for i, fruta := range frutas {
        fmt.Printf("%d: %s\n", i, fruta)
    }

    // Apenas valor (ignora índice com _)
    for _, fruta := range frutas {
        fmt.Println(fruta)
    }

    // Apenas índice
    for i := range frutas {
        fmt.Printf("Índice: %d\n", i)
    }
}

Range com Map

package main

import "fmt"

func main() {
    notas := map[string]float64{
        "Alice": 9.5,
        "Bob":   8.0,
        "Carol": 9.0,
    }

    // Ordem de iteração em maps é aleatória!
    for nome, nota := range notas {
        fmt.Printf("%s: %.1f\n", nome, nota)
    }

    // Apenas chaves
    for nome := range notas {
        fmt.Println("Aluno:", nome)
    }
}

Range com String

package main

import "fmt"

func main() {
    texto := "Olá"

    // Itera sobre runes (Unicode code points)
    for i, runa := range texto {
        fmt.Printf("Índice: %d, Rune: %c, Byte: %d\n", i, runa, runa)
    }
}

Range com Canal

package main

import "fmt"

func main() {
    numeros := make(chan int)

    go func() {
        for i := 0; i < 5; i++ {
            numeros <- i
        }
        close(numeros)
    }()

    // Range sobre canal até ele ser fechado
    for num := range numeros {
        fmt.Println(num)
    }
}

Controle de Execução

Break

Sai de um loop ou switch:

package main

import "fmt"

func main() {
    for i := 0; i < 10; i++ {
        if i == 5 {
            break  // Sai do loop quando i == 5
        }
        fmt.Println(i)
    }
    // Output: 0, 1, 2, 3, 4
}

Continue

Pula para a próxima iteração:

package main

import "fmt"

func main() {
    for i := 0; i < 10; i++ {
        if i%2 == 0 {
            continue  // Pula números pares
        }
        fmt.Println(i)
    }
    // Output: 1, 3, 5, 7, 9
}

Break com Labels

Sai de loops aninhados:

package main

import "fmt"

func main() {
    externo:
    for i := 0; i < 3; i++ {
        for j := 0; j < 3; j++ {
            if i == 1 && j == 1 {
                break externo  // Sai do loop externo
            }
            fmt.Printf("(%d, %d)\n", i, j)
        }
    }
    // Output: (0, 0), (0, 1), (0, 2), (1, 0)
}

Goto

Evite usar goto, mas conheça sua existência:

package main

import "fmt"

func main() {
    i := 0

loop:
    if i >= 5 {
        goto end
    }
    fmt.Println(i)
    i++
    goto loop

end:
    fmt.Println("Fim")
}

Exercícios Práticos

Exercício 1: FizzBuzz

Implemente o clássico FizzBuzz: para números de 1 a 100, imprima “Fizz” se divisível por 3, “Buzz” se divisível por 5, “FizzBuzz” se divisível por ambos, ou o número caso contrário.

Ver solução
package main

import "fmt"

func main() {
    for i := 1; i <= 100; i++ {
        switch {
        case i%15 == 0:
            fmt.Println("FizzBuzz")
        case i%3 == 0:
            fmt.Println("Fizz")
        case i%5 == 0:
            fmt.Println("Buzz")
        default:
            fmt.Println(i)
        }
    }
}

Exercício 2: Tabuada

Crie um programa que imprima a tabuada de um número usando loops aninhados.

Ver solução
package main

import "fmt"

func main() {
    // Tabuada de 1 a 10
    for i := 1; i <= 10; i++ {
        fmt.Printf("Tabuada do %d:\n", i)
        for j := 1; j <= 10; j++ {
            fmt.Printf("  %d x %d = %d\n", i, j, i*j)
        }
        fmt.Println()
    }
}

Exercício 3: Busca em Slice

Implemente uma função que busca um elemento em um slice e retorna seu índice (ou -1 se não encontrado).

Ver solução
package main

import "fmt"

func buscar(slice []int, alvo int) int {
    for i, v := range slice {
        if v == alvo {
            return i
        }
    }
    return -1
}

func main() {
    numeros := []int{10, 25, 30, 45, 50}
    
    indice := buscar(numeros, 30)
    if indice != -1 {
        fmt.Printf("Encontrado no índice %d\n", indice)
    } else {
        fmt.Println("Não encontrado")
    }
}

Exercício 4: Calculadora com Menu

Crie uma calculadora interativa com menu usando switch.

Ver solução
package main

import (
    "fmt"
)

func main() {
    var opcao int
    var a, b float64

    for {
        fmt.Println("\n=== Calculadora ===")
        fmt.Println("1. Soma")
        fmt.Println("2. Subtração")
        fmt.Println("3. Multiplicação")
        fmt.Println("4. Divisão")
        fmt.Println("0. Sair")
        fmt.Print("Escolha: ")
        fmt.Scan(&opcao)

        if opcao == 0 {
            fmt.Println("Até logo!")
            break
        }

        fmt.Print("Digite o primeiro número: ")
        fmt.Scan(&a)
        fmt.Print("Digite o segundo número: ")
        fmt.Scan(&b)

        switch opcao {
        case 1:
            fmt.Printf("Resultado: %.2f\n", a+b)
        case 2:
            fmt.Printf("Resultado: %.2f\n", a-b)
        case 3:
            fmt.Printf("Resultado: %.2f\n", a*b)
        case 4:
            if b == 0 {
                fmt.Println("Erro: divisão por zero")
            } else {
                fmt.Printf("Resultado: %.2f\n", a/b)
            }
        default:
            fmt.Println("Opção inválida")
        }
    }
}

Padrões Comuns

Iteração com Índice

for i := 0; i < len(slice); i++ {
    // Acesso por índice
}

Iteração com Range

for i, v := range slice {
    // i = índice, v = valor
}

Loop Infinito com Condição de Saída

for {
    // faz algo
    if condicao {
        break
    }
}

Retry com Limite

for tentativa := 0; tentativa < maxTentativas; tentativa++ {
    err := fazerAlgo()
    if err == nil {
        break  // Sucesso
    }
    if tentativa == maxTentativas-1 {
        return err  // Última tentativa falhou
    }
    time.Sleep(time.Second * time.Duration(tentativa+1))
}

Dicas e Melhores Práticas

1. Prefira Range

Use range quando possível — é mais idiomático:

// Bom
for _, item := range lista {
    processar(item)
}

// Evite (a menos que precise do índice)
for i := 0; i < len(lista); i++ {
    processar(lista[i])
}

2. Cuidado com Maps e Range

A ordem de iteração em maps é aleatória:

// Se precisar de ordem, ordene as chaves primeiro
var chaves []string
for k := range mapa {
    chaves = append(chaves, k)
}
sort.Strings(chaves)

for _, k := range chaves {
    fmt.Println(k, mapa[k])
}

3. Evite Modificar o Slice Durante Iteração

// Perigoso: comportamento indefinido
for i := range slice {
    if condicao(slice[i]) {
        slice = append(slice[:i], slice[i+1:]...)
    }
}

// Melhor: criar novo slice
var novoSlice []Tipo
for _, item := range slice {
    if !condicao(item) {
        novoSlice = append(novoSlice, item)
    }
}

4. Use Defer em Loops com Cuidado

// Ruim: defer dentro de loop acumula chamadas
for _, arquivo := range arquivos {
    f, _ := os.Open(arquivo)
    defer f.Close()  // Não fecha até a função retornar!
}

// Bom: função anônima
for _, arquivo := range arquivos {
    func() {
        f, _ := os.Open(arquivo)
        defer f.Close()
        // processa arquivo
    }()
}

Próximos Passos

Excelente! Você agora domina o controle de fluxo em Go. Prepare-se para o próximo nível:

Próximo Artigo da Série

📖 Concorrência em Go: Goroutines e Channels → — A feature mais poderosa de Go: programação concorrente simplificada.

Desafios

  1. Ordenação: Implemente Bubble Sort ou Selection Sort
  2. Primos: Encontre todos os números primos até N
  3. Palíndromo: Verifique se uma string é palíndromo
  4. Fibonacci: Gere a sequência de Fibonacci

Recursos


Artigo anterior: Sintaxe Básica de Go ←
Próximo artigo: Concorrência em Go: Goroutines e Channels →


Última atualização: 09 de fevereiro de 2026
Versão do Go: 1.23