Entendendo e Manipulando Maps na Linguagem Go

Em Go, o map é uma estrutura de dados poderosa que associa chaves a valores, funcionando de forma aáloga aos dicionários em Python ou HashMaps em Java. Trata-se de um tipo de referência, o que significa que, ao passar um map para uma função, ambos compartilharão a mesma estrutura de dados subjacente.

Declaração e Inicialização

A sintaxe básica para declarar um map é var nomeMap map[TipoChave]TipoValor. No entanto, um map declarado mas não inicializado possui o valor nil e não pode receber elementos. Para criar um map utilizável, empregamos a função make.

// Inicialização com make
precos := make(map[string]float64)
precos["cafe"] = 5.50

// Declaração seguida de inicialização
var estoque map[int]int
estoque = make(map[int]int)
estoque[101] = 50

fmt.Println(precos)

Embora os maps cresçam dinamicamente, é uma boa prática definir uma capacidade inicial se o tamanho aproximado for conhecido, visando otimização de performance: make(map[key]value, capacidade).

Restrições de Tipos

Chaves: Podem ser de qualquer tipo que suporte os operadores de comparação (== e !=). Isso inclui tipos básicos (string, int, float), ponteiros, interfaces e structs que contenham apenas campos comparáveis. Slices, maps e funções não podem ser usados como chaves.

Valores: Podem ser de qualquer tipo, inclunido tipos complexos, outras maps ou interface{} para armazenar valores heterogêneos.

Operações Essenciais

Inserção e Atualização

Para adicionar ou modificar um elemento, utiliza-se o operador de atribuição direta.

config := make(map[string]string)
config["timeout"] = "30s" // Inserção
config["timeout"] = "60s" // Atualização

Recuperação e Verificação de Existência

Ao acessar um elemento, Go retorna o valor correspondente. Se a chave não existir, o valor zero do tipo do valor será retornado. Para distinguir entre um valor zero real e a ausência da chave, utiliza-se o padrão "comma ok".

pontuacao := map[string]int{"Alice": 10, "Bob": 0}

// Verificação robusta
if valor, ok := pontuacao["Charlie"]; ok {
    fmt.Printf("Pontuação encontrada: %d\n", valor)
} else {
    fmt.Println("Usuário não cadastrado")
}

// Verificação apenas da existência
_, existe := pontuacao["Alice"]

Exclusão de Elementos

A função nativa delete remove uma chave do map. Caso a chave não exista, a operação não executa nenhuma ação e não gera erro.

usuarios := map[int]string{1: "Admin", 2: "Guest"}
delete(usuarios, 2)

Iteração com for-range

A iteração sobre um map é feita com o loop range. É importante notar que a ordem de iteração em maps no Go é aleatória e não garantida entre execuções.

catalogo := map[string]int{"A": 1, "B": 2, "C": 3}
for chave, valor := range catalogo {
    fmt.Printf("Chave: %s | Valor: %d\n", chave, valor)
}

Ordenação de Maps

Como maps não mantêm ordem, para processar os dados de forma ordenada, é necessário extrair as chaves para um slice, ordená-lo e então percorrer o slice acessando o map.

import "sort"

pontos := map[string]int{"Zebra": 10, "Abelha": 50, "Gato": 20}
var nomes []string

// 1. Extrair chaves
for nome := range pontos {
    nomes = append(nomes, nome)
}

// 2. Ordenar o slice de chaves
sort.Strings(nomes)

// 3. Iterar de forma ordenada
for _, nome := range nomes {
    fmt.Printf("%s: %d\n", nome, pontos[nome])
}

Tags: Golang data-structures maps backend

Publicado em 7-17 22:01