Introdução: Por que o cache é criticamente importante para aplicações Go
No desenvolvimento web moderno, a velocidade de resposta da aplicação impacta diretamente a experiência do usuário e a conversão. A linguagem Go (Golang) é conhecida por seu desempenho, mas mesmo a aplicação mais otimizada pode enfrentar gargalos ao trabalhar com bancos de dados ou APIs externas. É aqui que o cache entra em ação.
Cache é o armazenamento temporário de dados frequentemente solicitados em um repositório rápido. No ecossistema Go, existem três abordagens principais:
- Soluções embutidas (sync.Map, map + mutex) — para pequenos volumes de dados dentro de um único processo.
- Memcached — cache distribuído em memória, simples e rápido.
- Redis — repositório avançado com suporte a estruturas de dados, persistência e clusterização.
Neste artigo, analisaremos cada opção com exemplos práticos em Go, compararemos seu desempenho e daremos recomendações de escolha.
Cache embutido em Go: sync.Map e mapas concorrentes
Para cenários simples, onde o cache não precisa ser distribuído, o Go oferece ferramentas padrão. A opção mais popular é sync.Map, introduzida no Go 1.9.
Exemplo: sync.Map para cache de resultados de API
package main
import ( "fmt" "sync" "time")
type Cache struct { data sync.Map}
func (c *Cache) Get(key string) (interface{}, bool) { return c.data.Load(key)}
func (c *Cache) Set(key string, value interface{}, ttl time.Duration) { c.data.Store(key, value) time.AfterFunc(ttl, func() { c.data.Delete(key) })}
func main() { cache := &Cache{} cache.Set("user_42", "Alice", 5*time.Second)
if val, ok := cache.Get("user_42"); ok { fmt.Println("Cache contém:", val) }}Prós: dependência zero, segurança de concorrência, simplicidade.
Contras: sem evicção automática (exceto TTL via gambiarras), sem distribuição, desempenho limitado sob alta concorrência.
Para cenários mais complexos, use bibliotecas como go-cache ou bigcache, que oferecem TTL, evicção LFU/LRU e baixa latência.
Memcached em Go: cache distribuído leve e rápido
Memcached é um sistema de cache distribuído em memória. É ideal para armazenar pares simples "chave-valor" de tamanho pequeno (até 1 MB).
Conexão ao Memcached a partir do Go
Para trabalhar com Memcached, use a biblioteca github.com/bradfitz/gomemcache.
package main
import ( "fmt" "github.com/bradfitz/gomemcache/memcache")
func main() { mc := memcache.New("localhost:11211")
// Escrita no cache err := mc.Set(&memcache.Item{ Key: "user_100", Value: []byte(`{"name":"Bob","age":30}`), Expiration: 300, // 5 minutos }) if err != nil { panic(err) }
// Leitura do cache item, err := mc.Get("user_100") if err == nil { fmt.Printf("Dados: %s", item.Value) } else { fmt.Println("Cache miss") }}Quando escolher Memcached:
- Você precisa de um armazenamento simples chave-valor.
- O tamanho dos objetos não excede 1 MB.
- Não é necessária persistência ou estruturas de dados complexas.
- Alta velocidade de leitura/escrita (latência < 1 ms).
Limitações: sem replicação, sem transações, dados perdidos na reinicialização.
Redis em Go: ferramenta poderosa com recursos ricos
Redis não é apenas um cache, mas um repositório de dados completo em memória com suporte a strings, listas, conjuntos, hashes e até filas. Para Go, a melhor