---
title: "Controle de Fluxo em Go: if, switch, loops - Tutorial Completo"
url: "https://golang.com.br/tutoriais/golang-para-iniciantes/golang-controle-de-fluxo-if-switch-loops/"
markdown_url: "https://golang.com.br/tutoriais/golang-para-iniciantes/golang-controle-de-fluxo-if-switch-loops.MD"
description: "Aprenda controle de fluxo em Go. Tutorial completo sobre if/else, switch, for loops, range e controle de execução. Exemplos práticos para iniciantes."
date: "2026-02-09"
author: ""
---

# Controle de Fluxo em Go: if, switch, loops - Tutorial Completo

Aprenda controle de fluxo em Go. Tutorial completo sobre if/else, switch, for loops, range e controle de execução. Exemplos práticos para iniciantes.


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](./artigo-2-sintaxe-basica)**

## If e Else

Go tem uma sintaxe de condicionais limpa e direta.

### If Básico

```go
package main

import "fmt"

func main() {
    idade := 18

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

### If-Else

```go
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`:

```go
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:

```go
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

```go
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

```go
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:

```go
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:

```go
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:

```go
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)

```go
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

```go
package main

import "fmt"

func main() {
    contador := 0

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

### Loop Infinito

```go
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:

```go
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

```go
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

```go
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

```go
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:

```go
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:

```go
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:

```go
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:

```go
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.

<details>
<summary>Ver solução</summary>

```go
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)
        }
    }
}
```
</details>

### Exercício 2: Tabuada

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

<details>
<summary>Ver solução</summary>

```go
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()
    }
}
```
</details>

### 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).

<details>
<summary>Ver solução</summary>

```go
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")
    }
}
```
</details>

### Exercício 4: Calculadora com Menu

Crie uma calculadora interativa com menu usando switch.

<details>
<summary>Ver solução</summary>

```go
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")
        }
    }
}
```
</details>

## Padrões Comuns

### Iteração com Índice

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

### Iteração com Range

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

### Loop Infinito com Condição de Saída

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

### Retry com Limite

```go
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:

```go
// 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:

```go
// 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

```go
// 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

```go
// 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 →](./artigo-4-concorrencia)** — 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

- 📚 [Effective Go - Control structures](https://go.dev/doc/effective_go#control-structures)
- 🎓 [Go by Example - Flow Control](https://gobyexample.com/flow-control)

---

*Artigo anterior: [Sintaxe Básica de Go ←](./artigo-2-sintaxe-basica)*  
*Próximo artigo: [Concorrência em Go: Goroutines e Channels →](./artigo-4-concorrencia)*

---

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