O ecossistema Go oferece diversas bibliotecas para interação com o Redis, sendo a Redigo uma das mais consolidadas e amplamente utilizadas devido à sua interface baseada em comandos puros do Redis e suporte robusto para recursos avançados.
Instalação e Configuração
Para começar a utilizar a biblioteca em seu projeto, instale o pacote via terminal:
go get github.com/gomodule/redigo/redis
Estabelecendo Conexão
A interface central da biblioteca é a Conn. A conexão é estabelecida através da função Dial, e é fundamental garantir o fechamento da mesma para evitar vazamento de recursos.
package main
import (
"fmt"
"github.com/gomodule/redigo/redis"
)
func main() {
// Conectando ao servidor local
conexao, err := redis.Dial("tcp", "127.0.0.1:6379")
if err != nil {
fmt.Printf("Falha na conexão: %v\n", err)
return
}
defer conexao.Close()
}
Operações Básicas de String e Expiração
O método Do é utilizado para enviar comandso genéricos ao Redis. Para converter o retorno para tipos específicos do Go, a Redigo fornece funções auxiliares como redis.String.
// Definindo uma chave com valor e tempo de expiração
_, err = conexao.Do("SET", "sessao:usuario:101", "ativo")
_, err = conexao.Do("EXPIRE", "sessao:usuario:101", 3600) // 1 hora
// Recuperando o valor
status, err := redis.String(conexao.Do("GET", "sessao:usuario:101"))
if err == nil {
fmt.Printf("Status da sessão: %s\n", status)
}
Manipulação de Múltiplos Valores (MSET e MGET)
Para otimizar a latência, é possível processar várias chaves em uma única chamada de rede.
// Configuração múltipla
_, err = conexao.Do("MSET", "app:cor", "azul", "app:versao", "2.1.0")
// Leitura múltipla
valores, err := redis.Strings(conexao.Do("MGET", "app:cor", "app:versao"))
for i, v := range valores {
fmt.Printf("Item %d: %s\n", i, v)
}
Estruturas de Dados: Listas e Hashes
A biblioteca suporta todas as estruturas nativas do Redis. Abaixo, exemplos de manipulação de listas e mapas (hashes).
// Exemplo com Listas (Fila)
conexao.Do("RPUSH", "fila:tarefas", "processar_imagem", "enviar_email")
tarefa, _ := redis.String(conexao.Do("LPOP", "fila:tarefas"))
// Exemplo com Hashes
conexao.Do("HSET", "perfil:1", "username", "dev_golang", "nivel", 5)
nivel, _ := redis.Int(conexao.Do("HGET", "perfil:1", "nivel"))
fmt.Printf("Nível do usuário: %d\n", nivel)
Uso de Pipelining
O Pipelining permite enviar uma sequência de comandos sem esperar pela resposta de cada um individualmente, reduzindo o overhead de rede. Isso é feito através de Send, Flush e Receive.
// Adiciona comandos ao buffer de saída
conexao.Send("SET", "contador:A", 10)
conexao.Send("SET", "contador:B", 20)
conexao.Send("GET", "contador:A")
// Envia o buffer completo para o servidor
conexao.Flush()
// Recebe os resultados na ordem em que foram enviados
conexao.Receive() // Resposta do primeiro SET
conexao.Receive() // Resposta do segundo SET
res, _ := redis.Int(conexao.Receive())
fmt.Printf("Resultado do contador A: %d\n", res)
Modelo de Pub/Sub (Publicação e Assinatura)
Para sistemas orientados a eventos, a Redigo oferece o tipo PubSubConn.
func iniciarInscricao() {
c, _ := redis.Dial("tcp", "127.0.0.1:6379")
psc := redis.PubSubConn{Conn: c}
psc.Subscribe("notificacoes_sistema")
for {
switch v := psc.Receive().(type) {
case redis.Message:
fmt.Printf("Canal %s: mensagem: %s\n", v.Channel, v.Data)
case error:
return
}
}
}
func publicarEvento(msg string) {
c, _ := redis.Dial("tcp", "127.0.0.1:6379")
c.Do("PUBLISH", "notificacoes_sistema", msg)
}
Transações Atômicas
Transações no Redis garantem que um bloco de comandos seja executado de forma atômica utilizando MULTI e EXEC.
conexao.Send("MULTI")
conexao.Send("INCR", "metricas:acessos")
conexao.Send("INCR", "metricas:vendas")
resultado, err := conexao.Do("EXEC")
if err == nil {
fmt.Println("Transação concluída com sucesso:", resultado)
}
Conexão Avançada com Parâmetros
Em ambientes produtivos, é comum a necessidade de autenticação e seleção de bases de dados específicas.
func obterConexaoCustomizada() (redis.Conn, error) {
return redis.Dial("tcp", "10.0.0.50:6379",
redis.DialPassword("senha_segura"),
redis.DialDatabase(2),
)
}