Slices, Maps e Structs em Go — Referência Rápida

Estruturas de dados são o coração de qualquer programa Go. Esta referência cobre as operações mais usadas no dia a dia. Para conceitos fundamentais, veja Go para Iniciantes e o glossário de slice.


Arrays

Arrays em Go têm tamanho fixo definido em tempo de compilação. Na prática, slices são muito mais comuns.

package main

import "fmt"

func main() {
	// Declaração
	var a [5]int                      // [0 0 0 0 0]
	b := [3]string{"go", "rust", "zig"} // tamanho explícito
	c := [...]int{10, 20, 30}        // tamanho inferido

	fmt.Println(a, b, c)
	fmt.Println(len(a)) // 5
}
OperaçãoSintaxeNota
Declararvar a [5]intZero values
Literal[3]int{1, 2, 3}Tamanho fixo
Inferido[...]int{1, 2, 3}Compilador conta
Tamanholen(a)Sempre fixo
Comparara == bArrays são comparáveis (slices não)

Veja também arrays no glossário.


Slices

Slices são a estrutura de dados dinâmica mais usada em Go. Internamente, um slice é um struct com ponteiro, length e capacity.

Criar Slices

package main

import "fmt"

func main() {
	// Literal
	s := []int{1, 2, 3, 4, 5}

	// make(tipo, length, capacity)
	s2 := make([]int, 0, 10) // len=0, cap=10

	// A partir de array
	arr := [5]int{10, 20, 30, 40, 50}
	s3 := arr[1:4] // [20, 30, 40]

	// Nil slice vs empty slice
	var nilSlice []int          // nil, len=0, cap=0
	emptySlice := []int{}       // não-nil, len=0, cap=0

	fmt.Println(s, s2, s3, nilSlice == nil, emptySlice == nil)
}

Operações com Slices

OperaçãoCódigoResultado
Appends = append(s, 6, 7)Adiciona ao final
Sub-slices[1:3]Elementos do índice 1 até 2
Copycopy(dst, src)Copia min(len(dst), len(src))
Lengthlen(s)Número de elementos
Capacitycap(s)Capacidade alocada
Deletar índice iappend(s[:i], s[i+1:]...)Remove elemento
Inserir no índice iappend(s[:i], append([]T{v}, s[i:]...)...)Insere elemento

Padrões Comuns

package main

import "fmt"

func main() {
	s := []int{1, 2, 3, 4, 5}

	// Copiar um slice (evitar compartilhar backing array)
	copia := make([]int, len(s))
	copy(copia, s)

	// Filtrar
	var pares []int
	for _, v := range s {
		if v%2 == 0 {
			pares = append(pares, v)
		}
	}

	// Deletar índice 2
	i := 2
	s = append(s[:i], s[i+1:]...)

	// Converter para array (Go 1.20+)
	arr := [3]int([]int{10, 20, 30})

	fmt.Println(copia, pares, s, arr)
}

Atenção: append pode realocar o backing array. Sempre use s = append(s, ...). Veja cannot range over para erros comuns com iteração.


Maps

Maps são tabelas hash com chave tipada. Veja maps no glossário.

Criar e Operar

package main

import "fmt"

func main() {
	// Literal
	m := map[string]int{
		"alice": 90,
		"bob":   85,
	}

	// make
	m2 := make(map[string][]string) // map de slices

	// Set
	m["carol"] = 95

	// Get
	nota := m["alice"]

	// Get com verificação (comma ok idiom)
	nota, ok := m["dave"]
	if !ok {
		fmt.Println("dave não encontrado")
	}

	// Delete
	delete(m, "bob")

	// Tamanho
	fmt.Println(len(m))

	fmt.Println(m, m2, nota)
}

Iterar sobre Maps

package main

import (
	"fmt"
	"sort"
)

func main() {
	m := map[string]int{"c": 3, "a": 1, "b": 2}

	// Iteração (ordem NÃO garantida)
	for k, v := range m {
		fmt.Printf("%s: %d\n", k, v)
	}

	// Iteração ordenada por chave
	keys := make([]string, 0, len(m))
	for k := range m {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	for _, k := range keys {
		fmt.Printf("%s: %d\n", k, m[k])
	}
}
OperaçãoCódigoNota
Criarmake(map[K]V)Sempre use make ou literal
Setm[key] = valSobrescreve se existir
Getv := m[key]Retorna zero value se não existir
Check + Getv, ok := m[key]ok é false se ausente
Deletedelete(m, key)Seguro se key não existir
Lengthlen(m)Número de pares
Iterarfor k, v := range mOrdem aleatória

Atenção: maps não são thread-safe. Para acesso concorrente, use sync.RWMutex ou sync.Map. Veja o cheatsheet de concorrência.


Structs

Structs são tipos compostos que agrupam campos. Veja struct no glossário.

Definir e Usar

package main

import "fmt"

type Endereco struct {
	Rua    string
	Cidade string
	UF     string
}

type Pessoa struct {
	Nome     string
	Idade    int
	Endereco Endereco // composição
}

func main() {
	// Criação com campos nomeados (recomendado)
	p := Pessoa{
		Nome:  "Ana",
		Idade: 30,
		Endereco: Endereco{
			Rua:    "Rua Augusta",
			Cidade: "São Paulo",
			UF:     "SP",
		},
	}

	// Acesso a campos
	fmt.Println(p.Nome)
	fmt.Println(p.Endereco.Cidade)

	// Ponteiro para struct
	pp := &p
	pp.Idade = 31 // Go desreferencia automaticamente
}

Métodos

package main

import "fmt"

type Retangulo struct {
	Largura, Altura float64
}

// Receiver por valor (não altera o original)
func (r Retangulo) Area() float64 {
	return r.Largura * r.Altura
}

// Receiver por ponteiro (altera o original)
func (r *Retangulo) Escalar(fator float64) {
	r.Largura *= fator
	r.Altura *= fator
}

func main() {
	r := Retangulo{Largura: 10, Altura: 5}
	fmt.Println(r.Area()) // 50
	r.Escalar(2)
	fmt.Println(r.Area()) // 200
}

Veja methods no glossário e receiver no glossário.

Struct Tags

package main

import (
	"encoding/json"
	"fmt"
)

type Usuario struct {
	ID        int    `json:"id" db:"user_id"`
	Nome      string `json:"nome" validate:"required"`
	Email     string `json:"email,omitempty"`
	SenhaHash string `json:"-"` // não serializa
}

func main() {
	u := Usuario{ID: 1, Nome: "Ana", Email: "[email protected]"}
	data, _ := json.Marshal(u)
	fmt.Println(string(data))
	// {"id":1,"nome":"Ana","email":"[email protected]"}
}
TagPacoteUso
json:"nome"encoding/jsonSerialização JSON
json:"-"encoding/jsonIgnorar campo
json:",omitempty"encoding/jsonOmitir se vazio
db:"coluna"sqlx, pgxMapeamento de banco
validate:"required"go-playground/validatorValidação
yaml:"campo"gopkg.in/yaml.v3Serialização YAML

Veja também Go e PostgreSQL e sqlc para SQL type-safe.

Embedding (Composição)

Go usa composição em vez de herança. Veja interfaces em Go e composição no glossário.

package main

import "fmt"

type Animal struct {
	Nome string
}

func (a Animal) Falar() string {
	return a.Nome + " faz barulho"
}

type Cachorro struct {
	Animal // embedded — promove campos e métodos
	Raca   string
}

func main() {
	d := Cachorro{
		Animal: Animal{Nome: "Rex"},
		Raca:   "Pastor",
	}
	fmt.Println(d.Nome)   // acessa direto (promovido)
	fmt.Println(d.Falar()) // método promovido
}

Interfaces

Interfaces são satisfeitas implicitamente — sem implements. Veja interfaces no glossário e interfaces em Go.

package main

import (
	"fmt"
	"math"
)

type Forma interface {
	Area() float64
}

type Circulo struct{ Raio float64 }

func (c Circulo) Area() float64 {
	return math.Pi * c.Raio * c.Raio
}

type Retangulo struct{ L, A float64 }

func (r Retangulo) Area() float64 {
	return r.L * r.A
}

func imprimirArea(f Forma) {
	fmt.Printf("Área: %.2f\n", f.Area())
}

func main() {
	imprimirArea(Circulo{Raio: 5})
	imprimirArea(Retangulo{L: 10, A: 3})
}
ConceitoSintaxe
Definirtype Nome interface { Metodo() Tipo }
Interface vaziainterface{} ou any (Go 1.18+)
Type assertionv, ok := i.(Tipo)
Type switchswitch v := i.(type) { ... }

Veja cannot use X as type Y para erros comuns com interfaces e tipos. Para comparar estruturas de dados, veja como Rust implementa Vec, HashMap e structs com ownership, e como Python trabalha com listas, dicionários e dataclasses.


Veja Também