Como obter slice de chaves de map em Go: guia 2025

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

A eterna dor de cabeça do desenvolvedor Go: como extrair rapidamente todas as chaves de um map?

\n

Você já escreveu algo assim em Go?

\n
m := map[string]int{"go": 1, "python": 2, "rust": 3}\nkeys := make([]string, 0, len(m))\nfor k := range m {\n    keys = append(keys, k)\n}\n
\n

Se sim, você não está sozinho. Obter um slice de chaves de um map é uma das tarefas mais populares no Stack Overflow na categoria Go. A pergunta acumula milhares de visualizações e dezenas de respostas com abordagens diferentes. E não é surpresa: Go não tem uma função nativa keys() como Python ou JavaScript. Toda vez é preciso reinventar a roda.

\n

Mas 2025 trouxe mudanças. Com o lançamento do Go 1.22 e os generics, além de novos idioms, surgiram soluções mais elegantes. Neste artigo, vamos analisar todas as formas de obter um slice de chaves de um map — desde o clássico até as melhores práticas modernas. Vamos nessa!

\n\n

Por que Go não tem uma função keys() nativa?

\n

Antes de mergulhar no código, vamos entender a filosofia da linguagem. Go é minimalista. Seus criadores deliberadamente não adicionam funções que podem ser implementadas em uma única linha. for k := range m é a forma nativa de iterar sobre um map. Mas o problema é que:

\n
    \n
  • A ordem das chaves não é garantida (e isso é uma feature, não um bug)
  • \n
  • Não há açúcar sintático para "coletar tudo em um slice"
  • \n
  • Generics só surgiram no 1.18 e se consolidaram no 1.22
  • \n
\n

Por isso, a comunidade desenvolveu vários padrões. Vamos compará-los.

\n\n

Método 1: Loop clássico (nível básico)

\n

A forma mais simples e direta é a que mostramos no início. Funciona em qualquer versão do Go.

\n
func Keys(m map[string]int) []string {\n    keys := make([]string, 0, len(m))\n    for k := range m {\n        keys = append(keys, k)\n    }\n    return keys\n}\n
\n

Vantagens:

\n
    \n
  • Transparência — qualquer iniciante entende o que está acontecendo
  • \n
  • Sem dependências da versão do Go
  • \n
  • Fácil de modificar (por exemplo, adicionar filtros)
  • \n
\n

Desvantagens:

\n
    \n
  • Muito código repetitivo para cada map
  • \n
  • É necessário escrever uma função separada para cada tipo
  • \n
\n

Veredito: ótimo para exemplos didáticos ou tarefas pontuais. Mas em código de produção, a gente busca universalidade.

\n\n

Método 2: Generics (Go 1.18+)

\n

Com a chegada dos generics, foi possível criar uma única função para qualquer tipo de chave.

\n
func Keys[K comparable, V any](m map[K]V) []K {\n    keys := make([]K, 0, len(m))\n    for k := range m {\n        keys = append(keys, k)\n    }\n    return keys\n}\n\n// Uso:\nm := map[string]int{"a": 1, "b": 2}\nkeys := Keys(m) // []string{"a", "b"}\n
\n

Que beleza, não? Uma função só e tudo funciona. Go 1.22 tornou os generics ainda mais estáveis, então este método é o recomendado para novos projetos.

\n

Importante: as chaves precisam ser comparable. Isso é automaticamente verdade para todos os tipos padrão (string, int, float, struct sem slices, etc.).

\n\n

Método 3: Usando reflect (para casos exóticos)

\n

Às vezes, é preciso trabalhar com um map cujo tipo só é conhecido em tempo de execução. É aí que o pacote reflect entra em cena.

\n
func KeysReflect(m interface{}) []interface{} {\n    v := reflect.ValueOf(m)\n    if v.Kind() != reflect.Map {\n        return nil\n    }\n    keys := make([]interface{}, v.Len())\n    for i, k := range v.MapKeys() {\n        keys[i] = k.Interface()\n    }\n    return keys\n}\n
\n

Quando usar:

\n
    \n
  • Ao serializar/desserializar estruturas desconhecidas
  • \n
  • Em bibliotecas de uso geral
  • \n
  • Quando o tipo do map vem de uma fonte externa (JSON, YAML)

Blogs

Book Recommendations