### Create and Use a Redis Connection Pool Source: https://context7.com/gomodule/redigo/llms.txt Manages a pool of reusable Redis connections. Applications get a connection via `Get()` or `GetContext()` and return it by calling `Close()` on the connection. Configure pool parameters like timeouts and idle limits. ```go package main import ( "fmt" "log" "net/http" "time" "github.com/gomodule/redigo/redis" ) var pool *redis.Pool func newPool(addr string) *redis.Pool { return &redis.Pool{ MaxIdle: 10, MaxActive: 100, IdleTimeout: 240 * time.Second, MaxConnLifetime: 30 * time.Minute, Wait: true, // block until a connection is free Dial: func() (redis.Conn, error) { return redis.Dial("tcp", addr, redis.DialPassword("secret"), redis.DialConnectTimeout(5*time.Second), ) }, TestOnBorrow: func(c redis.Conn, t time.Time) error { if time.Since(t) < time.Minute { return nil } _, err := c.Do("PING") return err }, } } func handler(w http.ResponseWriter, r *http.Request) { conn := pool.Get() defer conn.Close() val, err := redis.String(conn.Do("GET", "greeting")) if err == redis.ErrNil { val = "Hello, World!" conn.Do("SET", "greeting", val, "EX", 60) } else if err != nil { http.Error(w, err.Error(), 500) return } fmt.Fprintln(w, val) } func main() { pool = newPool("localhost:6379") defer pool.Close() // Monitor pool stats stats := pool.Stats() fmt.Printf("Active: %d, Idle: %d\n", stats.ActiveCount, stats.IdleCount) http.HandleFunc("/", handler) log.Fatal(http.ListenAndServe(":8080", nil)) } ``` -------------------------------- ### Map Converters: StringMap, IntMap, Int64Map, Float64Map Source: https://context7.com/gomodule/redigo/llms.txt Convert flat key-value array replies from Redis commands like HGETALL and CONFIG GET into Go maps. ```APIDOC ## StringMap ### Description Converts a flat key-value array reply into a `map[string]string`. ### Method `redis.StringMap(reply interface{}, err error)` ### Parameters - `reply` (interface{}) - The reply from a Redis command. - `err` (error) - The error from the Redis command. ### Response - `map[string]string` - The converted map. - `error` - An error if the conversion fails. ### Request Example ```go user, err := redis.StringMap(c.Do("HGETALL", "user:1")) ``` ### Response Example ```go fmt.Println(user["name"]) ``` ``` -------------------------------- ### Convert Flat Key-Value Replies to map[string]string Source: https://context7.com/gomodule/redigo/llms.txt Use `redis.StringMap` to convert flat key-value array replies (e.g., from HGETALL, CONFIG GET) into a Go map. Ensure the Redis reply is a flat list of alternating keys and values. ```go package main import ( "fmt" "log" "github.com/gomodule/redigo/redis" ) func main() { c, _ := redis.Dial("tcp", "localhost:6379") defer c.Close() c.Do("HSET", "user:1", "name", "Alice", "age", "30", "score", "9.5") // map[string]string from HGETALL user, err := redis.StringMap(c.Do("HGETALL", "user:1")) if err != nil { log.Fatal(err) } fmt.Println(user["name"]) fmt.Println(user["age"]) // CONFIG GET returns alternating key-value pairs cfg, err := redis.StringMap(c.Do("CONFIG", "GET", "maxmemory*")) if err != nil { log.Fatal(err) } fmt.Println(cfg) } ``` -------------------------------- ### redis.SlowLogs / redis.Latencies / redis.LatencyHistories — Server diagnostics Source: https://context7.com/gomodule/redigo/llms.txt Parse the structured output of Redis `SLOWLOG GET`, `LATENCY LATEST`, and `LATENCY HISTORY` commands into typed Go structs. ```APIDOC ## redis.SlowLogs / redis.Latencies / redis.LatencyHistories ### Description Parse the structured output of Redis `SLOWLOG GET`, `LATENCY LATEST`, and `LATENCY HISTORY` commands into typed Go structs. ### Functions - `redis.SlowLogs(reply interface{}) ([]SlowLog, error)`: Parses `SLOWLOG GET` output. - `redis.Latencies(reply interface{}) ([]Latency, error)`: Parses `LATENCY LATEST` output. - `redis.LatencyHistories(reply interface{}) ([]LatencyHistory, error)`: Parses `LATENCY HISTORY` output. ### Return Types - `SlowLog` struct: - `ID` (uint64) - `Time` (int64) - `ExecutionTime` (int64) - `Args` ([]interface{}) - `ClientAddr` (string) - `Latency` struct: - `Name` (string) - `Latest` (int64) - `Max` (int64) - `LatencyHistory` struct: - `Time` (int64) - `ExecutionTime` (int64) ``` -------------------------------- ### Get Redis Connection with Context Timeout Source: https://context7.com/gomodule/redigo/llms.txt Respects context cancellation when waiting for a free connection. Useful for preventing operations from blocking indefinitely. ```go package main import ( "context" "fmt" "log" "time" "github.com/gomodule/redigo/redis" ) func main() { pool := &redis.Pool{ MaxActive: 5, Wait: true, Dial: func() (redis.Conn, error) { return redis.Dial("tcp", "localhost:6379") }, } defer pool.Close() ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) defer cancel() conn, err := pool.GetContext(ctx) if err != nil { log.Fatal(err) // context.DeadlineExceeded if pool exhausted and timeout reached } defer conn.Close() val, err := redis.String(conn.Do("GET", "mykey")) if err != nil && err != redis.ErrNil { log.Fatal(err) } fmt.Println(val) } ``` -------------------------------- ### redis.Pool Source: https://context7.com/gomodule/redigo/llms.txt Manages a pool of reusable Redis connections. Applications get a connection via Get() or GetContext() and return it by calling Close() on the connection. ```APIDOC ## `redis.Pool` — Thread-safe connection pool Manages a pool of reusable Redis connections. Applications get a connection via `Get()` or `GetContext()` and return it by calling `Close()` on the connection. ### Example Usage: ```go package main import ( "fmt" "log" "net/http" "time" "github.com/gomodule/redigo/redis" ) var pool *redis.Pool func newPool(addr string) *redis.Pool { return &redis.Pool{ MaxIdle: 10, MaxActive: 100, IdleTimeout: 240 * time.Second, MaxConnLifetime: 30 * time.Minute, Wait: true, // block until a connection is free Dial: func() (redis.Conn, error) { return redis.Dial("tcp", addr, redis.DialPassword("secret"), redis.DialConnectTimeout(5*time.Second), ) }, TestOnBorrow: func(c redis.Conn, t time.Time) error { if time.Since(t) < time.Minute { return nil } _, err := c.Do("PING") return err }, } } func handler(w http.ResponseWriter, r *http.Request) { conn := pool.Get() defer conn.Close() val, err := redis.String(conn.Do("GET", "greeting")) if err == redis.ErrNil { val = "Hello, World!" conn.Do("SET", "greeting", val, "EX", 60) } else if err != nil { http.Error(w, err.Error(), 500) return } fmt.Fprintln(w, val) } func main() { pool = newPool("localhost:6379") defer pool.Close() // Monitor pool stats stats := pool.Stats() fmt.Printf("Active: %d, Idle: %d\n", stats.ActiveCount, stats.IdleCount) http.HandleFunc("/", handler) log.Fatal(http.ListenAndServe(":8080", nil)) } ``` ``` -------------------------------- ### redis.Args / Args.Add / Args.AddFlat Source: https://context7.com/gomodule/redigo/llms.txt Builds variadic argument lists for Redis commands using a fluent interface. ```APIDOC ## Args and AddFlat ### Description A `[]interface{}` type with helper methods for fluently building command argument lists from scalars, slices, maps, and structs. `AddFlat` is particularly useful for flattening structs or maps into command arguments. ### Method `redis.Args(args ...interface{})` `Args.Add(arg interface{}) Args` `Args.AddFlat(v interface{}) Args` ### Parameters - `args ...interface{}` - Initial arguments for `redis.Args`. - `arg interface{}` - An argument to add using `Add`. - `v interface{}` - A value (struct, map, slice) to flatten and add using `AddFlat`. ### Response - `Args` - The modified argument builder. ### Request Example ```go type Profile struct { Name string `redis:"name"` Email string `redis:"email"` Score float64 `redis:"score,omitempty"` } p := Profile{Name: "Dave", Email: "dave@example.com", Score: 42.5} // Flatten a struct into HMSET args _, err := c.Do("HMSET", redis.Args{"user:5"}.AddFlat(p)...) // Flatten a map tags := map[string]interface{}{"lang": "go", "tier": "backend"} _, err = c.Do("HMSET", redis.Args{"meta"}.AddFlat(tags)...) // Variable-length SADD members := []string{"a", "b", "c", "d"} _, err = c.Do("SADD", redis.Args{"myset"}.AddFlat(members)...) ``` ### Response Example ```go result, _ := redis.StringMap(c.Do("HGETALL", "user:5")) fmt.Println(result["name"]) ``` ``` -------------------------------- ### Build Variadic Argument Lists with redis.Args Source: https://context7.com/gomodule/redigo/llms.txt Use `redis.Args` and its methods (`Add`, `AddFlat`) to fluently build command argument lists (`[]interface{}`) from scalars, slices, maps, and structs. This is helpful for commands with variable-length arguments or complex structures. ```go package main import ( "fmt" "log" "github.com/gomodule/redigo/redis" ) type Profile struct { Name string `redis:"name"` Email string `redis:"email"` Score float64 `redis:"score,omitempty"` } func main() { c, _ := redis.Dial("tcp", "localhost:6379") defer c.Close() // Flatten a struct into HMSET args p := Profile{Name: "Dave", Email: "dave@example.com", Score: 42.5} _, err := c.Do("HMSET", redis.Args{"user:5"}.AddFlat(p)...) if err != nil { log.Fatal(err) } // Flatten a map tags := map[string]interface{}{"lang": "go", "tier": "backend"} _, err = c.Do("HMSET", redis.Args{"meta"}.AddFlat(tags)...) if err != nil { log.Fatal(err) } // Variable-length SADD members := []string{"a", "b", "c", "d"} _, err = c.Do("SADD", redis.Args{"myset"}.AddFlat(members)...) if err != nil { log.Fatal(err) } result, _ := redis.StringMap(c.Do("HGETALL", "user:5")) fmt.Println(result["name"]) fmt.Println(result["email"]) } ``` -------------------------------- ### Connect to Redis with redis.DialURL Source: https://context7.com/gomodule/redigo/llms.txt Parses a Redis URI and connects, automatically handling host, port, password, database, and TLS. Ensure connections are closed using defer. ```go package main import ( "fmt" "log" "github.com/gomodule/redigo/redis" ) func main() { // Plain connection, database 2 c, err := redis.DialURL("redis://localhost:6379/2") if err != nil { log.Fatal(err) } defer c.Close() // Password-authenticated connection (requirepass style) c2, err := redis.DialURL("redis://:mypassword@localhost:6379/0") if err != nil { log.Fatal(err) } defer c2.Close() // ACL style: username:password c3, err := redis.DialURL("redis://alice:alicepassword@localhost:6379/0") if err != nil { log.Fatal(err) } defer c3.Close() // TLS (rediss scheme) c4, err := redis.DialURL("rediss://localhost:6380/0") if err != nil { log.Fatal(err) } defer c4.Close() pong, _ := redis.String(c.Do("PING")) fmt.Println(pong) // PONG } ``` -------------------------------- ### Vitess Resource Pool with Redigo Source: https://github.com/gomodule/redigo/wiki/Vitess-Example This Go program demonstrates how to use Vitess resource pools to manage Redigo Redis connections. It initializes a pool with a specified capacity and timeout, acquires a connection, executes a Redis command, and then releases the connection back to the pool. ```go package main import ( "log" "time" "github.com/garyburd/redigo/redis" "github.com/youtube/vitess/go/pools" "golang.org/x/net/context" ) // ResourceConn adapts a Redigo connection to a Vitess Resource. type ResourceConn struct { redis.Conn } func (r ResourceConn) Close() { r.Conn.Close() } func main() { p := pools.NewResourcePool(func() (pools.Resource, error) { c, err := redis.Dial("tcp", ":6379") return ResourceConn{c}, err }, 1, 2, time.Minute) defer p.Close() ctx := context.TODO() r, err := p.Get(ctx) if err != nil { log.Fatal(err) } defer p.Put(r) c := r.(ResourceConn) n, err := c.Do("INFO") if err != nil { log.Fatal(err) } log.Printf("info=%s", n) } ``` -------------------------------- ### Pipeline Multiple Redis Commands with Redigo Source: https://context7.com/gomodule/redigo/llms.txt Efficiently send multiple commands by buffering them with `Conn.Send`, transmitting them in a single round trip with `Conn.Flush`, and then receiving individual replies with `Conn.Receive`. This significantly reduces network overhead for bulk operations. It can also be used for Redis transactions with `MULTI`/`EXEC`. ```go package main import ( "fmt" "log" "github.com/gomodule/redigo/redis" ) func main() { c, err := redis.Dial("tcp", "localhost:6379") if err != nil { log.Fatal(err) } defer c.Close() // Pipeline three SET commands c.Send("SET", "key1", "value1") c.Send("SET", "key2", "value2") c.Send("SET", "key3", "value3") if err := c.Flush(); err != nil { log.Fatal(err) } for i := 0; i < 3; i++ { if _, err := c.Receive(); err != nil { log.Fatal(err) } } // Pipelined transaction: MULTI/EXEC c.Send("MULTI") c.Send("INCR", "counter") c.Send("INCR", "counter") replies, err := redis.Values(c.Do("EXEC")) if err != nil { log.Fatal(err) } var v1, v2 int redis.Scan(replies, &v1, &v2) fmt.Println(v1, v2) // 1 2 } ``` -------------------------------- ### Execute Single Redis Command with Redigo Source: https://context7.com/gomodule/redigo/llms.txt Use `Conn.Do` to send a single Redis command, flush the buffer, and read a single reply. This is the most common method for interacting with Redis. Ensure proper error handling for each command. ```go package main import ( "fmt" "log" "github.com/gomodule/redigo/redis" ) func main() { c, err := redis.Dial("tcp", "localhost:6379") if err != nil { log.Fatal(err) } defer c.Close() // SET and GET if _, err := c.Do("SET", "user:1:name", "Alice"); err != nil { log.Fatal(err) } name, err := redis.String(c.Do("GET", "user:1:name")) if err != nil { log.Fatal(err) } fmt.Println(name) // Alice // INCR count, err := redis.Int(c.Do("INCR", "visits")) if err != nil { log.Fatal(err) } fmt.Println(count) // 1 // EXISTS (returns bool) exists, err := redis.Bool(c.Do("EXISTS", "user:1:name")) if err != nil { log.Fatal(err) } fmt.Println(exists) // true // DEL if _, err := c.Do("DEL", "visits", "user:1:name"); err != nil { log.Fatal(err) } } ``` -------------------------------- ### Context-aware Redis Connection with redis.DialContext Source: https://context7.com/gomodule/redigo/llms.txt Establishes a connection to Redis while respecting context cancellation and deadlines during the handshake. Ensure connections are closed using defer. ```go package main import ( "context" "log" "time" "github.com/gomodule/redigo/redis" ) func main() { ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() c, err := redis.DialContext(ctx, "tcp", "localhost:6379", redis.DialPassword("secret"), ) if err != nil { log.Fatal(err) } defer c.Close() } ``` -------------------------------- ### Call Redis Command with Variable Arguments Source: https://github.com/gomodule/redigo/wiki/FAQ Use the '...' notation to pass a slice of arguments to a variadic command. Ensure the slice is of type []interface{}, or convert it before calling. ```go // Set fields in HASH "myhash" using values from map fvs. var args = []interface{}{"myhash"} for f, v := range fvs { args = append(args, f, v) } _, err := conn.Do("HMSET", args...) ``` -------------------------------- ### redis.DialURL Source: https://context7.com/gomodule/redigo/llms.txt Parses a Redis URI (`redis://`, `rediss://`, `valkey://`, `valkeys://`) and connects, automatically handling host, port, password, database, and TLS. ```APIDOC ## redis.DialURL / redis.DialURLContext ### Description Parses a Redis URI (`redis://`, `rediss://`, `valkey://`, `valkeys://`) and connects, automatically handling host, port, password, database, and TLS. `DialURLContext` respects context cancellation and deadlines. ### Method `redis.DialURL(rawurl string) (Conn, error)` `redis.DialURLContext(ctx context.Context, rawurl string) (Conn, error)` ### Parameters #### `rawurl` (string) - The Redis URI to parse and connect with (e.g., "redis://:mypassword@localhost:6379/0"). ### Request Example ```go // Plain connection, database 2 c, err := redis.DialURL("redis://localhost:6379/2") if err != nil { log.Fatal(err) } defer c.Close() // Password-authenticated connection c2, err := redis.DialURL("redis://:mypassword@localhost:6379/0") if err != nil { log.Fatal(err) } defer c2.Close() // ACL style: username:password c3, err := redis.DialURL("redis://alice:alicepassword@localhost:6379/0") if err != nil { log.Fatal(err) } defer c3.Close() // TLS (rediss scheme) c4, err := redis.DialURL("rediss://localhost:6380/0") if err != nil { log.Fatal(err) } defer c4.Close() ``` ### Response #### Success Response - `Conn` (redis.Conn) - A connection object implementing the `redis.Conn` interface. - `error` - An error if the connection fails. ``` -------------------------------- ### Structured Pub/Sub with Type-Switch Receive Source: https://context7.com/gomodule/redigo/llms.txt Wraps a `Conn` with Pub/Sub methods and provides a typed `Receive` function. Handles `Message`, `Subscription`, `Pong`, or `error` types. ```go package main import ( "context" "fmt" "log" "time" "github.com/gomodule/redigo/redis" ) func listenChannels(ctx context.Context, addr string, channels ...string) error { c, err := redis.Dial("tcp", addr, redis.DialReadTimeout(2*time.Minute), redis.DialWriteTimeout(10*time.Second), ) if err != nil { return err } defer c.Close() psc := redis.PubSubConn{Conn: c} if err := psc.Subscribe(redis.Args{}.AddFlat(channels)...); err != nil { return err } done := make(chan error, 1) go func() { for { switch v := psc.Receive().(type) { case redis.Message: fmt.Printf("[%s] %s\n", v.Channel, v.Data) case redis.Subscription: fmt.Printf("subscribed to %s (%d total)\n", v.Channel, v.Count) if v.Count == 0 { done <- nil return } case error: done <- v return } } }() ticker := time.NewTicker(time.Minute) defer ticker.Stop() for { select { case <-ticker.C: if err := psc.Ping("healthcheck"); err != nil { return err } case <-ctx.Done(): psc.Unsubscribe() return <-done case err := <-done: return err } } } func main() { ctx, cancel := context.WithCancel(context.Background()) defer cancel() go func() { c, _ := redis.Dial("tcp", "localhost:6379") defer c.Close() time.Sleep(100 * time.Millisecond) c.Do("PUBLISH", "news", "breaking story") cancel() }() if err := listenChannels(ctx, "localhost:6379", "news", "alerts"); err != nil { log.Fatal(err) } } ``` -------------------------------- ### Conn.Do Source: https://context7.com/gomodule/redigo/llms.txt Executes a single Redis command, flushes the output buffer, and reads a single reply. This is the most common method for interacting with Redis and also handles draining any pending pipelined replies. ```APIDOC ## Conn.Do — Execute a single command and receive the reply Sends a command, flushes the output buffer, and reads a single reply. The most common way to interact with Redis. Also drains any pending pipelined replies before returning. ### Method `Do(command string, args ...interface{}) (reply interface{}, err error)` ### Parameters - `command` (string): The Redis command to execute (e.g., "SET", "GET"). - `args` (...interface{}): Arguments for the Redis command. ### Example Usage ```go // SET and GET if _, err := c.Do("SET", "user:1:name", "Alice"); err != nil { log.Fatal(err) } name, err := redis.String(c.Do("GET", "user:1:name")) if err != nil { log.Fatal(err) } fmt.Println(name) // Alice // INCR count, err := redis.Int(c.Do("INCR", "visits")) if err != nil { log.Fatal(err) } fmt.Println(count) // 1 // EXISTS (returns bool) exists, err := redis.Bool(c.Do("EXISTS", "user:1:name")) if err != nil { log.Fatal(err) } fmt.Println(exists) // true // DEL if _, err := c.Do("DEL", "visits", "user:1:name"); err != nil { log.Fatal(err) } ``` ``` -------------------------------- ### Connect to Redis with redis.Dial Source: https://context7.com/gomodule/redigo/llms.txt Establishes a raw TCP or TLS connection to Redis using functional options. Ensure connections are closed using defer. ```go package main import ( "fmt" "log" "time" "github.com/gomodule/redigo/redis" ) func main() { // Basic connection c, err := redis.Dial("tcp", "localhost:6379") if err != nil { log.Fatal(err) } defer c.Close() // Connection with options: password, DB select, and timeouts c2, err := redis.Dial("tcp", "localhost:6379", redis.DialPassword("secret"), redis.DialDatabase(1), redis.DialConnectTimeout(5*time.Second), redis.DialReadTimeout(3*time.Second), redis.DialWriteTimeout(3*time.Second), ) if err != nil { log.Fatal(err) } defer c2.Close() // ACL authentication (Redis 6+) c3, err := redis.Dial("tcp", "localhost:6379", redis.DialUsername("alice"), redis.DialPassword("alicepassword"), ) if err != nil { log.Fatal(err) } defer c3.Close() // TLS connection c4, err := redis.Dial("tcp", "redis.example.com:6380", redis.DialUseTLS(true), redis.DialTLSSkipVerify(false), ) if err != nil { log.Fatal(err) } defer c4.Close() reply, _ := c.Do("PING") fmt.Println(reply) // PONG } ``` -------------------------------- ### redis.PubSubConn Source: https://context7.com/gomodule/redigo/llms.txt Structured Pub/Sub with type-switch receive. Wraps a Conn with Subscribe, PSubscribe, Unsubscribe, PUnsubscribe, Ping, and a typed Receive that returns Message, Subscription, Pong, or error. ```APIDOC ## `redis.PubSubConn` — Structured Pub/Sub with type-switch receive Wraps a `Conn` with `Subscribe`, `PSubscribe`, `Unsubscribe`, `PUnsubscribe`, `Ping`, and a typed `Receive` that returns `Message`, `Subscription`, `Pong`, or `error`. ### Example Usage: ```go package main import ( "context" "fmt" "log" "time" "github.com/gomodule/redigo/redis" ) func listenChannels(ctx context.Context, addr string, channels ...string) error { c, err := redis.Dial("tcp", addr, redis.DialReadTimeout(2*time.Minute), redis.DialWriteTimeout(10*time.Second), ) if err != nil { return err } defer c.Close() psc := redis.PubSubConn{Conn: c} if err := psc.Subscribe(redis.Args{}.AddFlat(channels)...); err != nil { return err } done := make(chan error, 1) go func() { for { switch v := psc.Receive().(type) { case redis.Message: fmt.Printf("[%s] %s\n", v.Channel, v.Data) case redis.Subscription: fmt.Printf("subscribed to %s (%d total)\n", v.Channel, v.Count) if v.Count == 0 { done <- nil return } case error: done <- v return } } }() ticker := time.NewTicker(time.Minute) defer ticker.Stop() for { select { case <-ticker.C: if err := psc.Ping("healthcheck"); err != nil { return err } case <-ctx.Done(): psc.Unsubscribe() return <-done case err := <-done: return err } } } func main() { ctx, cancel := context.WithCancel(context.Background()) defer cancel() go func() { c, _ := redis.Dial("tcp", "localhost:6379") defer c.Close() time.Sleep(100 * time.Millisecond) c.Do("PUBLISH", "news", "breaking story") cancel() }() if err := listenChannels(ctx, "localhost:6379", "news", "alerts"); err != nil { log.Fatal(err) } } ``` ``` -------------------------------- ### Parse Redis Server Diagnostics Source: https://context7.com/gomodule/redigo/llms.txt Demonstrates parsing output from Redis SLOWLOG, LATENCY LATEST, and LATENCY HISTORY commands. Requires an active Redis connection. ```go package main import ( "fmt" "log" "github.com/gomodule/redigo/redis" ) func main() { c, _ := redis.Dial("tcp", "localhost:6379") defer c.Close() // Slow log logs, err := redis.SlowLogs(c.Do("SLOWLOG", "GET", "10")) if err != nil { log.Fatal(err) } for _, entry := range logs { fmt.Printf("id=%d time=%s exec=%s cmd=%v client=%s\n", entry.ID, entry.Time, entry.ExecutionTime, entry.Args, entry.ClientAddr) } // Latency latest latencies, err := redis.Latencies(c.Do("LATENCY", "LATEST")) if err != nil { log.Fatal(err) } for _, l := range latencies { fmt.Printf("event=%s latest=%s max=%s\n", l.Name, l.Latest, l.Max) } // Latency history for a specific event history, err := redis.LatencyHistories(c.Do("LATENCY", "HISTORY", "command")) if err != nil { log.Fatal(err) } for _, h := range history { fmt.Printf("time=%s exec=%s\n", h.Time, h.ExecutionTime) } } ``` -------------------------------- ### redis.NewScript / Script.Do Source: https://context7.com/gomodule/redigo/llms.txt Optimistic EVALSHA with fallback to EVAL. Pre-computes the SHA1 hash of a Lua script. Do first tries EVALSHA; if the script isn't loaded on the server it transparently falls back to EVAL, ensuring the script is loaded for subsequent calls. ```APIDOC ## redis.NewScript / Script.Do ### Description Pre-computes the SHA1 hash of a Lua script. `Do` first tries `EVALSHA`; if the script isn't loaded on the server it transparently falls back to `EVAL`, ensuring the script is loaded for subsequent calls. ### Usage ```go // Example script definition var myScript = redis.NewScript(numberOfKeys, "lua script body") // Executing the script reply, err := myScript.Do(conn, arg1, arg2, ...) // Loading the script (optional, Do handles missing scripts) err = myScript.Load(conn) ``` ### Parameters - `numberOfKeys` (int): The number of keys the script will use. - `lua script body` (string): The Lua script to be executed. - `conn` (*redis.Conn): The Redis connection. - `args` (...interface{}): Arguments to be passed to the Lua script. ### Response - `reply` (interface{}): The reply from the Redis server. - `err` (error): An error if the operation fails. ``` -------------------------------- ### Redis Commands with Custom Timeouts and Context Source: https://context7.com/gomodule/redigo/llms.txt Use `DoWithTimeout` for commands that require a specific read timeout, overriding the connection's default. `DoContext` allows cancellation via a `context.Context`, useful for managing long-running operations or graceful shutdowns. ```go package main import ( "context" "fmt" "log" "time" "github.com/gomodule/redigo/redis" ) func main() { c, err := redis.Dial("tcp", "localhost:6379", redis.DialReadTimeout(1*time.Second), ) if err != nil { log.Fatal(err) } defer c.Close() // Block up to 5 seconds waiting for a list element reply, err := redis.DoWithTimeout(c, 5*time.Second, "BLPOP", "mylist", 5) if err != nil { log.Fatal(err) } fmt.Println(reply) // Cancel via context ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() reply2, err := redis.DoContext(c, ctx, "BLPOP", "otherlist", 0) if err != nil { log.Fatal(err) } fmt.Println(reply2) } ``` -------------------------------- ### Pool.Stats — Connection pool metrics Source: https://context7.com/gomodule/redigo/llms.txt Returns a snapshot of pool statistics for integration with monitoring systems (Prometheus, Datadog, etc.). ```APIDOC ## Pool.Stats ### Description Returns a snapshot of pool statistics for integration with monitoring systems (Prometheus, Datadog, etc.). ### Method `Stats()` ### Returns - `Stats` struct containing: - `ActiveCount` (int): Number of active connections. - `IdleCount` (int): Number of idle connections. - `WaitCount` (int): Number of times a connection wait was attempted. - `WaitDuration` (time.Duration): Total duration spent waiting for connections. ``` -------------------------------- ### Pool.GetContext Source: https://context7.com/gomodule/redigo/llms.txt Pool connection with context. Respects context cancellation when waiting for a free connection. ```APIDOC ## `Pool.GetContext` — Pool connection with context Respects context cancellation when waiting for a free connection. ### Example Usage: ```go package main import ( "context" "fmt" "log" "time" "github.com/gomodule/redigo/redis" ) func main() { pool := &redis.Pool{ MaxActive: 5, Wait: true, Dial: func() (redis.Conn, error) { return redis.Dial("tcp", "localhost:6379") }, } defer pool.Close() ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) defer cancel() conn, err := pool.GetContext(ctx) if err != nil { log.Fatal(err) // context.DeadlineExceeded if pool exhausted and timeout reached } defer conn.Close() val, err := redis.String(conn.Do("GET", "mykey")) if err != nil && err != redis.ErrNil { log.Fatal(err) } fmt.Println(val) } ``` ``` -------------------------------- ### Optimistic EVALSHA with fallback to EVAL using redis.NewScript Source: https://context7.com/gomodule/redigo/llms.txt Pre-computes the SHA1 hash of a Lua script. `Do` first tries `EVALSHA`; if the script isn't loaded on the server it transparently falls back to `EVAL`, ensuring the script is loaded for subsequent calls. Use this for scripts that are frequently executed. ```go package main import ( "fmt" "log" "github.com/gomodule/redigo/redis" ) // atomicSetIfGreater sets key to value only if value > current value. // Returns 1 if updated, 0 otherwise. var setIfGreater = redis.NewScript(1, ` local current = tonumber(redis.call('GET', KEYS[1])) or 0 local new = tonumber(ARGV[1]) if new > current then redis.call('SET', KEYS[1], ARGV[1]) return 1 end return 0 `) // zpopScript atomically pops the lowest-score member from a sorted set. var zpopScript = redis.NewScript(1, ` local r = redis.call('ZRANGE', KEYS[1], 0, 0) if r ~= nil then r = r[1] redis.call('ZREM', KEYS[1], r) end return r `) func main() { c, err := redis.Dial("tcp", "localhost:6379") if err != nil { log.Fatal(err) } defer c.Close() // Pre-load script (optional; Do handles missing scripts automatically) if err := setIfGreater.Load(c); err != nil { log.Fatal(err) } updated, err := redis.Int(setIfGreater.Do(c, "highscore", 42)) if err != nil { log.Fatal(err) } fmt.Println("updated:", updated) // 1 updated, err = redis.Int(setIfGreater.Do(c, "highscore", 10)) if err != nil { log.Fatal(err) } fmt.Println("updated:", updated) // 0 (10 < 42) // Use zpopScript c.Do("ZADD", "jobs", 1, "low-priority", 10, "high-priority", 5, "medium") job, err := redis.String(zpopScript.Do(c, "jobs")) if err != nil { log.Fatal(err) } fmt.Println("next job:", job) // low-priority } ``` -------------------------------- ### Collect Redis Pool Statistics Source: https://context7.com/gomodule/redigo/llms.txt Periodically collects and prints connection pool statistics. Ensure a redis.Pool is initialized before calling this function. ```go package main import ( "fmt" "time" "github.com/gomodule/redigo/redis" ) func collectStats(pool *redis.Pool) { ticker := time.NewTicker(10 * time.Second) defer ticker.Stop() for range ticker.C { stats := pool.Stats() fmt.Printf( "active=%d idle=%d waitCount=%d waitDuration=%s\n", stats.ActiveCount, stats.IdleCount, stats.WaitCount, stats.WaitDuration, ) } } ``` -------------------------------- ### Conn.Send / Conn.Flush / Conn.Receive Source: https://context7.com/gomodule/redigo/llms.txt Pipeline multiple Redis commands for efficiency. Commands are buffered using `Send`, transmitted in a single network round trip with `Flush`, and their replies are read individually using `Receive`. This significantly reduces network overhead for bulk operations. ```APIDOC ## Conn.Send / Conn.Flush / Conn.Receive — Pipeline multiple commands Buffers commands with `Send`, transmits them in one round trip with `Flush`, and reads replies individually with `Receive`. Significantly reduces network overhead for bulk operations. ### `Conn.Send` #### Method `Send(command string, args ...interface{}) error` #### Description Buffers a command to be sent to the Redis server. ### `Conn.Flush` #### Method `Flush() error` #### Description Transmits all buffered commands to the Redis server. ### `Conn.Receive` #### Method `Receive() (reply interface{}, err error)` #### Description Reads a single reply from the Redis server for a previously sent command. ### Example Usage ```go // Pipeline three SET commands c.Send("SET", "key1", "value1") c.Send("SET", "key2", "value2") c.Send("SET", "key3", "value3") if err := c.Flush(); err != nil { log.Fatal(err) } for i := 0; i < 3; i++ { if _, err := c.Receive(); err != nil { log.Fatal(err) } } // Pipelined transaction: MULTI/EXEC c.Send("MULTI") c.Send("INCR", "counter") c.Send("INCR", "counter") replies, err := redis.Values(c.Do("EXEC")) if err != nil { log.Fatal(err) } var v1, v2 int redis.Scan(replies, &v1, &v2) fmt.Println(v1, v2) // 1 2 ``` ``` -------------------------------- ### Slice Converters Source: https://context7.com/gomodule/redigo/llms.txt Convert array replies to typed Go slices. ```APIDOC ## Slice Converters ### Description These functions convert Redis array replies into typed Go slices. ### Functions - `redis.Strings(reply interface{}, err error) ([]string, error)` - `redis.Ints(reply interface{}, err error) ([]int, error)` - `redis.Int64s(reply interface{}, err error) ([]int64, error)` - `redis.Float64s(reply interface{}, err error) ([]float64, error)` - `redis.ByteSlices(reply interface{}, err error) ([][]byte, error)` - `redis.Values(reply interface{}, err error) ([]interface{}, error)` ### Usage ```go // Example for redis.Strings strs, err := redis.Strings(c.Do("LRANGE", "mylist", 0, -1)) if err != nil { // Handle error } // Use strs // Example for redis.Values and redis.Scan c.Do("MSET", "k1", "1", "k2", "2") vals, err := redis.Values(c.Do("MGET", "k1", "k2")) if err != nil { // Handle error } var v1, v2 int redis.Scan(vals, &v1, &v2) // Use v1, v2 ``` ### Error Handling - Returns the input error if it's non-nil. - Handles type conversions for elements within the array. ``` -------------------------------- ### Multiplex Redis Connections with ConnMux Source: https://context7.com/gomodule/redigo/llms.txt Uses redisx.NewConnMux to allow multiple logical redis.Conn instances to share a single TCP connection. Not suitable for commands that set server-side state like pub/sub or transactions. ```go package main import ( "fmt" "log" "sync" "github.com/gomodule/redigo/redis" "github.com/gomodule/redigo/redisx" ) func main() { underlying, err := redis.Dial("tcp", "localhost:6379") if err != nil { log.Fatal(err) } mux := redisx.NewConnMux(underlying) defer mux.Close() var wg sync.WaitGroup for i := 0; i < 5; i++ { wg.Add(1) go func(n int) { defer wg.Done() c := mux.Get() defer c.Close() key := fmt.Sprintf("worker:%d", n) if _, err := c.Do("SET", key, n*10); err != nil { log.Println(err) return } val, err := redis.Int(c.Do("GET", key)) if err != nil { log.Println(err) return } fmt.Printf("%s = %d\n", key, val) }(i) } wg.Wait() } ``` -------------------------------- ### redisx.NewConnMux — Multiplex logical connections over one TCP connection Source: https://context7.com/gomodule/redigo/llms.txt Allows multiple logical `redis.Conn` instances to share a single underlying TCP connection. Not suitable for commands that set server-side state (pub/sub, transactions). ```APIDOC ## redisx.NewConnMux ### Description Multiplex logical connections over one TCP connection. Allows multiple logical `redis.Conn` instances to share a single underlying TCP connection. Not suitable for commands that set server-side state (pub/sub, transactions). ### Function `redisx.NewConnMux(c redis.Conn) *ConnMux` ### Parameters - `c` (`redis.Conn`): The underlying `redis.Conn` to multiplex. ### Returns - `*ConnMux`: A new `ConnMux` instance. ### Methods on `ConnMux` - `Get() redis.Conn`: Returns a logical `redis.Conn` from the multiplexer. - `Close()`: Closes the underlying connection and all logical connections. ``` -------------------------------- ### redis.Dial Source: https://context7.com/gomodule/redigo/llms.txt Establishes a raw TCP (or TLS) connection to Redis using functional options. All returned connections implement the redis.Conn interface and must be closed by the caller. ```APIDOC ## redis.Dial ### Description Establishes a raw TCP (or TLS) connection to Redis using functional options. All returned connections implement the `redis.Conn` interface and must be closed by the caller. ### Method `redis.Dial(network, address string, options ...DialOption) (Conn, error)` ### Parameters #### Network - `network` (string) - The network type (e.g., "tcp", "unix"). - `address` (string) - The server address (e.g., "localhost:6379"). #### Options - `redis.DialPassword(password string)` - Sets the password for authentication. - `redis.DialDatabase(db int)` - Selects the database. - `redis.DialConnectTimeout(timeout time.Duration)` - Sets the connection timeout. - `redis.DialReadTimeout(timeout time.Duration)` - Sets the read timeout. - `redis.DialWriteTimeout(timeout time.Duration)` - Sets the write timeout. - `redis.DialUsername(username string)` - Sets the username for ACL authentication. - `redis.DialUseTLS(useTLS bool)` - Enables TLS encryption. - `redis.DialTLSSkipVerify(skipVerify bool)` - Skips TLS certificate verification. ### Request Example ```go // Basic connection c, err := redis.Dial("tcp", "localhost:6379") if err != nil { log.Fatal(err) } defer c.Close() // Connection with options c2, err := redis.Dial("tcp", "localhost:6379", redis.DialPassword("secret"), redis.DialDatabase(1), redis.DialConnectTimeout(5*time.Second), ) if err != nil { log.Fatal(err) } defer c2.Close() ``` ### Response #### Success Response - `Conn` (redis.Conn) - A connection object implementing the `redis.Conn` interface. - `error` - An error if the connection fails. ```