Table of contents
Part of nurago, a collection of independent Go packages for backend services.
import "github.com/tecnickcom/nurago/pkg/redis"
Key/value operations, typed payloads and Pub/Sub over go-redis.
c, err := redis.New(ctx, &redis.SrvOptions{Addr: "localhost:6379"})
defer c.Close()
err = c.SetData(ctx, "key", value, time.Hour)
err = c.GetData(ctx, "key", &value)
Typed payloads
SetData and GetData serialise and deserialise around the raw string operations, so a struct goes in and comes back out without the call site handling encoding.
DefaultMessageEncodeFunc and DefaultMessageDecodeFunc are replaceable, which matters when the data has to be readable by something that is not this service. A shared cache populated by a Go service and read by a Python one needs an encoding both understand, and that choice belongs at construction rather than at each call.
The raw string operations remain available for values that are already bytes.
The address is validated before dialling
New validates the server address before attempting a connection, covering both TCP host:port and Unix domain sockets. Validation is skipped when a client is injected through WithRedisClient, since nothing is dialled.
A malformed address otherwise produces a connection error at first use, in a request, rather than at startup where a deployment can fail cleanly.
Pub/Sub outlives the New context
This is the behaviour most likely to surprise, and the doc comment is explicit about it.
When channels are declared with WithChannels, a subscription feeds Receive and ReceiveData one message per call. The subscription runs until Close is called. Cancelling the context passed to New does not stop it.
So a service that cancels its startup context after initialisation still has a live subscription, and one that relies on context cancellation for shutdown leaks the goroutine and the connection. Close is the only way to stop it, and it belongs in the shutdown path rather than in a defer on a startup function.
This mirrors the split in sqlconn: the constructor’s context bounds establishment, not the lifetime of the thing constructed.
One message per call
Receive returns a single message per invocation rather than handing back a channel.
That keeps back-pressure at the call site. A consumer loop processes one message and asks for the next when ready, so a slow consumer does not accumulate an unbounded in-memory backlog the way a buffered channel would.
Redis Pub/Sub is fire-and-forget: there is no acknowledgement, no replay, and a message published while no subscriber is connected is gone. For work that must not be lost, use kafka or sqs.
Health check and injection
Client.HealthCheck satisfies the healthcheck contract directly.
WithRedisClient injects a client, which is how tests substitute a mock or a miniredis instance without a server.
SrvOptions is an alias for go-redis Options, so pool sizing, TLS, credentials and timeouts are configured exactly as the underlying library documents, with no translation layer to learn.
Dependencies
Reaches github.com/redis/go-redis.
Links
- Reference documentation
- Source code
- The Valkey equivalent: valkey
- Durable messaging: kafka, sqs
- All nurago packages