Série Go: Loops, Funções, Structs e Mapas

🚀 Nesse: Episódio 04, descobriremos porque Go não possui loop while.


Série Go: Loops, Funções, Structs e Mapas


Neste quarto episódio da série sobre a linguagem Go, vamos direto ao ponto em quatro pilares essenciais para qualquer aplicação robusta: estruturas de repetição, funções, structs e mapas.

Nesse artigo vamos dar prosseguimento a nossa Série Go, os tópicos anteriores são:

Aqui você entenderá como Go simplifica o controle de fluxo com seu único loop for, como modularizar o código com funções, como modelar dados com structs, e como armazenar pares chave-valor com mapas. Essencial para quem quer escrever código limpo, performático e idiomático em Go.


Loops

Golang (ou Go) OFERECE APENAS UMA ESTRUTURA DE LOOP: o for. Não há while ou do-while.

Essa simplicidade faz parte da filosofia da linguagem. A seguir, estão os usos e variações do for em Go.

  • Sintaxe Básica
for i := 0; i < 10; i++ {
    fmt.Println(i)
}

Equivalente ao for tradicional em C/C++/Java.

  • Loop Condicional (estilo while)
i := 0
for i < 10 {
    fmt.Println(i)
    i++
}

Se omitir a inicialização e o incremento, o for age como um while.

  • Loop Infinito
for {
    // execução contínua
}

Precisa de um break para terminar.

Loop com range. Para iterar sobre arrays, slices, maps, strings ou canais.

  • Slice
nums := []int{1, 2, 3}
for i, v := range nums {
    fmt.Println(i, v)
}
  • Map
m := map[string]int{"a": 1, "b": 2}
for k, v := range m {
    fmt.Println(k, v)
}
  • String (em runas)
for i, c := range "gölang" {
    fmt.Printf("%d: %c\n", i, c)
}

Palavras-chave de controle

  • break: Sai do loop.
  • continue: Vai para a próxima iteração.
  • goto: Evitado, mas existe.

Exemplo com break e continue

for i := 0; i < 10; i++ {
    if i == 5 {
        continue
    }
    if i == 8 {
        break
    }
    fmt.Println(i)
}

Funções

Em Go, funções são blocos de código reutilizáveis que executam uma tarefa específica. Elas são definidas com a palavra-chave func, e podem retornar múltiplos valores, algo incomum em muitas linguagens.

  • Declaração de Funções
func nomeDaFuncao(param1 tipo1, param2 tipo2) tipoRetorno {
    // corpo da função
}
  • Exemplo:
func soma(a int, b int) int {
    return a + b
}
  • Os tipos podem ser agrupados:
func soma(a, b int) int {
    return a + b
}
  • Retorno Múltiplo

    Go permite múltiplos retornos:

func dividir(dividendo, divisor int) (int, error) {
    if divisor == 0 {
        return 0, fmt.Errorf("divisão por zero")
    }
    return dividendo / divisor, nil
}
  • Funções Nomeadas

    Os valores de retorno podem ser nomeados:

func operacoes(a, b int) (soma, produto int) {
    soma = a + b
    produto = a * b
    return
}
  • Funções Variádicas

    Aceitam número variável de argumentos:

func somar(nums ...int) int {
    total := 0
    for _, num := range nums {
        total += num
    }
    return total
}
  • Funções como Valores

    Funções são cidadãos de primeira classe:

func aplicar(f func(int, int) int, a, b int) int {
    return f(a, b)
}
  • Closures

    Funções podem capturar variáveis do escopo:

func contador() func() int {
    i := 0
    return func() int {
        i++
        return i
    }
}
  • Funções Anônimas

    Podem ser usadas diretamente:

resultado := func(a, b int) int {
    return a + b
}(2, 3)
  • Recursão

    Funções podem chamar a si mesmas:

func fatorial(n int) int {
    if n == 0 {
        return 1
    }
    return n * fatorial(n-1)
}


Structs

Em Go, structs são tipos compostos que agrupam variáveis sob um mesmo nome, permitindo representar entidades com múltiplos atributos. Elas são essenciais para a programação orientada a dados na linguagem, já que Go não tem classes como linguagens OO tradicionais.

  • Structs são passadas por valor, exceto quando usadas como ponteiros.
  • Campos exportados começam com letra maiúscula.
  • Structs são a base para JSON, XML e comunicação em rede via encoding/json, etc.

  • Definição
type Pessoa struct {
    Nome  string
    Idade int
}

Essa struct Pessoa agrupa dois campos: Nome e Idade.

  • Instanciação
p1 := Pessoa{"João", 30}
p2 := Pessoa{Nome: "Maria", Idade: 25}
p3 := Pessoa{}
p3.Nome = "Carlos"
p3.Idade = 40
  • Acesso a Campos
fmt.Println(p1.Nome)  // João
p2.Idade = 26
  • Structs como Ponteiros

    Go permite trabalhar com ponteiros para structs, economizando memória e evitando cópias desnecessárias:

p := &Pessoa{Nome: "Ana", Idade: 22}
p.Idade++ // sintaxe simplificada, Go desreferencia automaticamente
  • Métodos com Structs
func (p Pessoa) Saudacao() string {
    return "Olá, " + p.Nome
}
  • Métodos com receptor valor não alteram o original. Para modificar o estado:
func (p *Pessoa) Envelhecer() {
    p.Idade++
}
  • Structs Anônimas
p := struct {
    Nome string
    Idade int
}{"Lucas", 28}
  • Composição (embedding)

    Go usa composição em vez de herança:

type Endereco struct {
    Rua string
    Numero int
}

type Cliente struct {
    Pessoa
    Endereco
    ClienteDesde int
}

Campos embutidos podem ser acessados diretamente: cliente.Rua


Mapas

Mapas em Go são estruturas de dados baseadas em chave-valor, semelhantes aos dicionários em Python ou objetos em JavaScript. Eles permitem armazenar, acessar e manipular pares de dados de forma eficiente.

  • Declaração e Inicialização
var m map[string]int
m = make(map[string]int)

Ou de forma mais concisa:

m := make(map[string]int)

Também é possível inicializar diretamente com valores:

m := map[string]int{
    "apple":  2,
    "banana": 5,
}
  • Operações Básicas
  • Inserção
m["orange"] = 3
  • Leitura
val := m["apple"]
  • Verificação de Existência
val, ok := m["banana"]
if ok {
    // chave existe
}
  • Exclusão
delete(m, "orange")
  • Iteração
for key, value := range m {
    fmt.Println(key, value)
}
  • Referências

    Mapas são estruturas de referência, ou seja, ao passar para funções, você está passando o ponteiro internamente.

func modify(m map[string]int) {
    m["new"] = 42
}
  • Cuidados
  • Acesso a mapas não é seguro para concorrência. Use sync.Map ou mecanismos de sincronização (sync.Mutex) se necessário.
  • O valor zero de um mapa é nil. Você precisa inicializá-lo com make() antes de usar.

  • Exemplo Completo
package main

import "fmt"

func main() {
    fruits := map[string]int{
        "apple":  10,
        "banana": 15,
    }

    fruits["mango"] = 7

    for fruit, qty := range fruits {
        fmt.Printf("%s: %d\n", fruit, qty)
    }

    delete(fruits, "banana")
}

Nsse episódio finalizamos o CORE de Go, a partir dos próximos episódio veremos implementações na prática!


go series-go


Compartilhe


Nosso canal no Youtube

Inscreva-se


Marcos Oliveira

Marcos Oliveira

Desenvolvedor de software
https://github.com/terroo


Crie Aplicativos Gráficos para Linux e Windows com C++

Aprenda C++ Moderno e crie Games, Programas CLI, GUI e TUI de forma fácil.

Saiba Mais

Receba as novidades no seu e-mail!

Após cadastro e confirmação do e-mail, enviaremos semanalmente resumos e também sempre que houver novidades por aqui para que você mantenha-se atualizado!