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ção | Sintaxe | Nota |
|---|---|---|
| Declarar | var a [5]int | Zero values |
| Literal | [3]int{1, 2, 3} | Tamanho fixo |
| Inferido | [...]int{1, 2, 3} | Compilador conta |
| Tamanho | len(a) | Sempre fixo |
| Comparar | a == b | Arrays 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ção | Código | Resultado |
|---|---|---|
| Append | s = append(s, 6, 7) | Adiciona ao final |
| Sub-slice | s[1:3] | Elementos do índice 1 até 2 |
| Copy | copy(dst, src) | Copia min(len(dst), len(src)) |
| Length | len(s) | Número de elementos |
| Capacity | cap(s) | Capacidade alocada |
| Deletar índice i | append(s[:i], s[i+1:]...) | Remove elemento |
| Inserir no índice i | append(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:
appendpode realocar o backing array. Sempre uses = 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ção | Código | Nota |
|---|---|---|
| Criar | make(map[K]V) | Sempre use make ou literal |
| Set | m[key] = val | Sobrescreve se existir |
| Get | v := m[key] | Retorna zero value se não existir |
| Check + Get | v, ok := m[key] | ok é false se ausente |
| Delete | delete(m, key) | Seguro se key não existir |
| Length | len(m) | Número de pares |
| Iterar | for k, v := range m | Ordem aleatória |
Atenção: maps não são thread-safe. Para acesso concorrente, use
sync.RWMutexousync.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]"}
}
| Tag | Pacote | Uso |
|---|---|---|
json:"nome" | encoding/json | Serialização JSON |
json:"-" | encoding/json | Ignorar campo |
json:",omitempty" | encoding/json | Omitir se vazio |
db:"coluna" | sqlx, pgx | Mapeamento de banco |
validate:"required" | go-playground/validator | Validação |
yaml:"campo" | gopkg.in/yaml.v3 | Serializaçã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})
}
| Conceito | Sintaxe |
|---|---|
| Definir | type Nome interface { Metodo() Tipo } |
| Interface vazia | interface{} ou any (Go 1.18+) |
| Type assertion | v, ok := i.(Tipo) |
| Type switch | switch 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
- Cheatsheet: Sintaxe Básica — Variáveis, tipos e funções
- Cheatsheet: Concorrência — Goroutines e channels
- Cheatsheet: Strings e Formatação — Manipulação de strings
- Cheatsheet: Testes e Debug — Testing e profiling
- Tratamento de Erros em Go — Padrões de error handling
- Go para Backend — Aplicações práticas