Cache em Go (Golang): Redis e outras ferramentas
Cache é um dos mecanismos-chave para otimizar o desempenho de aplicações web e microsserviços. No ecossistema Go (Golang), existem diversas bibliotecas para implementar cache, desde soluções simples in-memory até sistemas distribuídos baseados em Redis. Neste artigo, vamos detalhar três abordagens principais: estruturas de dados nativas (sync.Map), bibliotecas in-memory populares (go-cache, freecache, bigcache) e integração com Redis.
1. Ferramentas nativas: sync.Map
Go oferece um map thread-safe — sync.Map. Ele é adequado para cache simples com pequeno volume de dados e atualizações raras. No entanto, seu desempenho em altas cargas é inferior ao de bibliotecas especializadas.
Exemplo de uso do sync.Map:
package main
import ( "fmt" "sync" "time")
func main() { var cache sync.Map
// Escrita cache.Store("user:42", map[string]interface{}{ "name": "Alice", "age": 30, })
// Leitura com verificação if val, ok := cache.Load("user:42"); ok { fmt.Println("Cache encontrado:", val) }
// Remoção cache.Delete("user:42")
// Cache com TTL (precisa ser implementado manualmente) cache.Store("session:abc", time.Now().Unix())}Desvantagens: ausência de TTL automático, conjunto limitado de operações, possíveis problemas de desempenho em escritas frequentes.
2. Bibliotecas In-memory
Para cenários mais complexos, use bibliotecas especializadas. Vejamos três populares:
2.1 go-cache
Biblioteca simples com suporte a TTL. Ideal para projetos pequenos.
import "github.com/patrickmn/go-cache"
func main() { c := cache.New(5*time.Minute, 10*time.Minute) // TTL padrão, intervalo de limpeza
c.Set("key", "value", cache.DefaultExpiration) val, found := c.Get("key") if found { fmt.Println(val) }}2.2 freecache
Biblioteca com tamanho de memória fixo (sem overhead de GC). Suporta TTL e alta performance.
import "github.com/coocood/freecache"
func main() { cache := freecache.NewCache(100 * 1024 * 1024) // 100 MB
cache.Set([]byte("mykey"), []byte("myvalue"), 60) // TTL 60 seg val, err := cache.Get([]byte("mykey")) if err == nil { fmt.Println(string(val)) }}2.3 bigcache
Otimizada para armazenar grandes volumes de dados sem pausas de GC. Trabalha com dados serializados.
import "github.com/allegro/bigcache/v3"
func main() { cache, _ := bigcache.NewBigCache(bigcache.DefaultConfig(10 * time.Minute))
cache.Set("key", []byte("value")) val, _ := cache.Get("key") fmt.Println(string(val))}3. Redis: cache distribuído
Para sistemas distribuídos e microsserviços, o Redis continua sendo o padrão de facto. Em Go, use a biblioteca go-redis/redis (v9+).
Conexão e operações básicas:
import ( "context" "fmt" "github.com/redis/go-redis/v9")
func main() { ctx := context.Background() rdb := redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: "", DB: 0, })
// Definir valor com TTL err := rdb.Set(ctx, "user:42", `{"name":"Bob"}`, 10*time.Minute).Err() if err != nil { panic(err) }
// Leitura val, err := rdb.Get(ctx, "user:42").Result() if err == redis.Nil { fmt.Println("Cache não encontrado") } else if err != nil { panic(err) } else { fmt.Println("Valor:", val) }}Recursos avançados do Redis em Go:
- Pipeline