### Install LibRedis Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Installs the LibRedis Go library using Go modules. This is the first step to integrate the library into your Go project. ```bash go get github.com/therealbill/libredis ``` -------------------------------- ### Basic DialConfig Example Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Provides a basic example of creating a DialConfig for a standard TCP connection to Redis. It sets essential parameters like network, address, and connection pool size. ```go config := &client.DialConfig{ Network: "tcp", Address: "localhost:6379", Database: 0, Password: "", Timeout: 5 * time.Second, MaxIdle: 10, TCPKeepAlive: 60, } ``` -------------------------------- ### Caching with Redis Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Provides examples for implementing a caching layer using Redis. It covers fetching data from the cache and setting data with a Time-To-Live (TTL). ```go // Caching func getFromCache(key string) ([]byte, error) { data, err := redisClient.Get("cache:" + key) if err != nil { return nil, err } if data == nil { return nil, nil // Cache miss } return data, nil } func setCache(key string, data []byte, ttl int) error { return redisClient.Setex("cache:"+key, ttl, string(data)) } ``` -------------------------------- ### Import LibRedis Client Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Demonstrates how to import the LibRedis client package into your Go source files. ```go import "github.com/therealbill/libredis/client" ``` -------------------------------- ### Redis Hash Operations in Go Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Demonstrates setting and getting individual fields, setting multiple fields, and retrieving all fields from a Redis hash using the Go client library. Includes error handling for each operation. ```go // Set hash fields success, err := redis.HSet("user:1", "name", "John Doe") if err != nil { log.Fatal("HSet failed:", err) } // Get hash field name, err := redis.HGet("user:1", "name") if err != nil { log.Fatal("HGet failed:", err) } if name != nil { fmt.Println("User name:", string(name)) } // Set multiple fields fields := map[string]string{ "email": "john@example.com", "age": "30", } err = redis.HMSet("user:1", fields) if err != nil { log.Fatal("HMSet failed:", err) } // Get all fields userdata, err := redis.HGetAll("user:1") if err != nil { log.Fatal("HGetAll failed:", err) } fmt.Println("User data:", userdata) ``` -------------------------------- ### Redis Streams Operations in Go (Redis 5.0+) Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Provides examples for using Redis Streams in Go, including adding events to a stream, reading from streams, creating consumer groups, and processing messages with acknowledgments. Demonstrates XAdd, XRead, XGroupCreate, XReadGroup, and XAck. ```go // Add events to a stream fields := map[string]string{ "user_id": "123", "action": "login", "ip": "192.168.1.100", } entryID, err := redis.XAdd("events", client.StreamIDAutoGenerate, fields) if err != nil { log.Fatal("XAdd failed:", err) } fmt.Println("Added event with ID:", entryID) // Read from streams streams := map[string]string{"events": "0-0"} // Read from beginning messages, err := redis.XRead(streams) if err != nil { log.Fatal("XRead failed:", err) } for _, msg := range messages { fmt.Printf("Stream: %s\n", msg.Stream) for _, entry := range msg.Entries { fmt.Printf(" ID: %s, Fields: %v\n", entry.ID, entry.Fields) } } // Consumer groups for reliable processing err = redis.XGroupCreate("events", "processors", client.StreamIDLatest) if err != nil { log.Printf("Group creation failed (may already exist): %v", err) } // Read as a consumer consumerStreams := map[string]string{"events": ">"} groupMessages, err := redis.XReadGroup("processors", "worker1", consumerStreams) if err != nil { log.Fatal("XReadGroup failed:", err) } // Process and acknowledge messages for _, msg := range groupMessages { for _, entry := range msg.Entries { fmt.Printf("Processing: %v\n", entry.Fields) // Acknowledge message after processing ackCount, err := redis.XAck("events", "processors", entry.ID) if err != nil { log.Printf("XAck failed: %v", err) } else { fmt.Printf("Acknowledged %d messages\n", ackCount) } } } ``` -------------------------------- ### Connect to Redis with DialConfig Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Establishes a connection to a Redis server using a detailed configuration object. It includes settings for network, address, database, password, and timeouts. The example also shows how to ping the server to verify the connection. ```go package main import ( "fmt" "log" "time" "github.com/therealbill/libredis/client" ) func main() { // Connect to Redis redis, err := client.DialWithConfig(&client.DialConfig{ Network: "tcp", Address: "127.0.0.1:6379", Database: 0, Password: "", Timeout: 5 * time.Second, MaxIdle: 10, }) if err != nil { log.Fatal("Failed to connect to Redis:", err) } defer redis.Close() // Test connection err = redis.Ping() if err != nil { log.Fatal("Failed to ping Redis:", err) } fmt.Println("Connected to Redis successfully!") } ``` -------------------------------- ### SSL DialConfig Example Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Illustrates how to configure a DialConfig for a secure SSL/TLS connection to Redis. This includes enabling SSL, specifying certificate paths, and handling verification settings. ```go config := &client.DialConfig{ Network: "tcp", Address: "redis.example.com:6380", Database: 0, Password: "secret", Timeout: 10 * time.Second, MaxIdle: 20, SSL: true, SSLSkipVerify: false, SSLCert: "/path/to/client.crt", SSLKey: "/path/to/client.key", SSLCA: "/path/to/ca.crt", } ``` -------------------------------- ### Good: Consistent Key Naming Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Promotes the use of consistent and predictable key naming conventions. This improves code readability, maintainability, and reduces the likelihood of key collisions. ```go // ✅ Good: Consistent key naming const ( UserPrefix = "user:" SessionPrefix = "session:" CachePrefix = "cache:" ) func getUserKey(userID string) string { return UserPrefix + userID } ``` -------------------------------- ### Go: Publish and Consume Redis Stream Events Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Demonstrates how to produce events to a Redis Stream using `XAdd` and consume them with a consumer group using `XReadGroupWithOptions`. Includes event handling and acknowledgment. ```go // Event producer func publishEvent(eventType, userID string, data map[string]string) error { fields := make(map[string]string) fields["event_type"] = eventType fields["user_id"] = userID fields["timestamp"] = time.Now().Format(time.RFC3339) // Copy additional data for k, v := range data { fields[k] = v } _, err := redisClient.XAdd("events", client.StreamIDAutoGenerate, fields) return err } // Event consumer worker func processEvents(consumerGroup, consumerName string) { // Create consumer group if it doesn't exist redisClient.XGroupCreate("events", consumerGroup, client.StreamIDLatest) for { streams := map[string]string{"events": ">"} opts := client.XReadGroupOptions{ Count: 10, Block: 5000, // 5 second timeout } messages, err := redisClient.XReadGroupWithOptions(consumerGroup, consumerName, streams, opts) if err != nil { log.Printf("Error reading from stream: %v", err) continue } for _, msg := range messages { for _, entry := range msg.Entries { // Process the event if err := handleEvent(entry.Fields); err != nil { log.Printf("Error processing event %s: %v", entry.ID, err) continue } // Acknowledge successful processing redisClient.XAck("events", consumerGroup, entry.ID) } } } } func handleEvent(fields map[string]string) error { eventType := fields["event_type"] userID := fields["user_id"] switch eventType { case "user_login": log.Printf("User %s logged in", userID) case "purchase": log.Printf("User %s made a purchase: %s", userID, fields["product"]) default: log.Printf("Unknown event type: %s", eventType) } return nil } ``` -------------------------------- ### Rate Limiting with Redis Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Provides an example of implementing a simple rate limiting mechanism using Redis. It utilizes the `INCR` command to count requests within a time window and `EXPIRE` to manage the window. ```go // Rate Limiting func checkRateLimit(userID string, limit int64, window int) (bool, error) { key := "rate_limit:" + userID current, err := redisClient.Incr(key) if err != nil { return false, err } if current == 1 { // First request, set expiration err = redisClient.Expire(key, window) if err != nil { return false, err } } return current <= limit, nil } ``` -------------------------------- ### Good: Environment-Based Configuration Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Shows how to configure the Redis client using environment variables, allowing for flexible deployment across different environments. It includes helper functions for reading environment variables. ```go // ✅ Good: Environment-based configuration func createRedisConfig() *client.DialConfig { return &client.DialConfig{ Network: getEnv("REDIS_NETWORK", "tcp"), Address: getEnv("REDIS_ADDRESS", "localhost:6379"), Password: getEnv("REDIS_PASSWORD", ""), Database: getEnvInt("REDIS_DB", 0), Timeout: time.Duration(getEnvInt("REDIS_TIMEOUT", 5)) * time.Second, MaxIdle: getEnvInt("REDIS_MAX_IDLE", 10), } } func getEnv(key, defaultValue string) string { if value := os.Getenv(key); value != "" { return value } return defaultValue } // Assume getEnvInt is defined elsewhere to parse int from env vars ``` -------------------------------- ### Good: Proper Resource Cleanup Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Illustrates the importance of closing Redis connections when they are no longer needed, typically using `defer`. This ensures resources are released promptly and prevents leaks. ```go // ✅ Good: Proper cleanup func main() { redis, err := client.DialWithConfig(config) if err != nil { log.Fatal(err) } defer redis.Close() // Always close connections // Your application logic here } ``` -------------------------------- ### Bad: Inconsistent Key Naming Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Demonstrates inconsistent key naming practices, which can lead to confusion and errors. It shows variations in prefixes, casing, and separators. ```go // ❌ Bad: Inconsistent naming func badExample() { redisClient.Set("user_123", "data") redisClient.Set("USER:456", "data") redisClient.Set("users/789", "data") } ``` -------------------------------- ### Session Management with Redis Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Demonstrates how to manage user sessions using Redis Hash data structures. It includes saving session data and setting an expiration time for the session. ```go // Session Management func saveSession(sessionID string, userData map[string]string) error { key := "session:" + sessionID err := redisClient.HMSet(key, userData) if err != nil { return err } return redisClient.Expire(key, 3600) // 1 hour expiration } func getSession(sessionID string) (map[string]string, error) { return redisClient.HGetAll("session:" + sessionID) } ``` -------------------------------- ### Redis Basic SSL/TLS Configuration in Go Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Illustrates how to establish a secure connection to Redis using SSL/TLS by setting the SSL option and specifying the server address and port. ```go config := &client.DialConfig{ Network: "tcp", Address: "secure-redis.example.com:6380", Password: "secure_password", SSL: true, SSLSkipVerify: false, // Verify certificates in production } redis, err := client.DialWithConfig(config) if err != nil { log.Fatal("SSL connection failed:", err) } ``` -------------------------------- ### Good: Single Redis Connection Instance Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Demonstrates the recommended approach of maintaining a single, shared Redis client instance throughout the application's lifecycle. This avoids the overhead and potential issues of creating new connections for each operation. ```go // ✅ Good: Single connection instance var redisClient *client.Redis func init() { var err error redisClient, err = client.DialWithConfig(&client.DialConfig{ Network: "tcp", Address: "localhost:6379", MaxIdle: 10, Timeout: 5 * time.Second, }) if err != nil { log.Fatal("Redis connection failed:", err) } } ``` -------------------------------- ### Redis String Operations Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Demonstrates common Redis string commands: SET for storing values, GET for retrieving them, SETEX for setting values with an expiration time, and INCR for atomic incrementing of integer values. ```go // Set and get string values err := redis.Set("username", "john_doe") if err != nil { log.Fatal("Set failed:", err) } value, err := redis.Get("username") if err != nil { log.Fatal("Get failed:", err) } fmt.Println("Username:", string(value)) // Set with expiration err = redis.Setex("session_token", 3600, "abc123") if err != nil { log.Fatal("Setex failed:", err) } // Increment counters count, err := redis.Incr("page_views") if err != nil { log.Fatal("Incr failed:", err) } fmt.Println("Page views:", count) ``` -------------------------------- ### Redis Graceful Shutdown in Go Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Demonstrates the correct way to close Redis connections managed by libredis, ensuring all pooled connections are properly released during application shutdown. ```go // Graceful shutdown func gracefulShutdown(redis *client.Redis) { redis.Close() // Closes all pooled connections } ``` -------------------------------- ### Redis Set Operations in Go Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Shows how to add members to a Redis set, check for membership, and retrieve all members from a set using the Go client library. Includes error handling for each operation. ```go // Add members to set count, err := redis.SAdd("tags", "redis", "database", "nosql") if err != nil { log.Fatal("SAdd failed:", err) } fmt.Println("Added tags:", count) // Check membership isMember, err := redis.SIsMember("tags", "redis") if err != nil { log.Fatal("SIsMember failed:", err) } fmt.Println("Is 'redis' a tag?", isMember) // Get all members members, err := redis.SMembers("tags") if err != nil { log.Fatal("SMembers failed:", err) } fmt.Println("All tags:", members) ``` -------------------------------- ### Redis Custom Error Handling Function in Go Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Provides an example of a Go function that encapsulates Redis operations and returns specific errors for common scenarios like missing data or failed retrieval. ```go // Graceful error handling func getUser(redis *client.Redis, userID string) (map[string]string, error) { userData, err := redis.HGetAll("user:" + userID) if err != nil { return nil, fmt.Errorf("failed to get user %s: %w", userID, err) } if len(userData) == 0 { return nil, fmt.Errorf("user %s not found", userID) } return userData, nil } ``` -------------------------------- ### Bad: Creating New Connections Per Operation Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Illustrates an anti-pattern where a new Redis connection is established for every operation. This is inefficient, consumes excessive resources, and can lead to performance degradation. ```go // ❌ Bad: Creating new connections for each operation func badExample() { redis, _ := client.DialWithConfig(config) // Don't do this repeatedly redis.Set("key", "value") redis.Close() } ``` -------------------------------- ### Redis Basic Error Handling in Go Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Illustrates how to handle errors when interacting with Redis using libredis. Covers checking for nil return values when a key does not exist and handling connection errors. ```go // Handle different types of errors value, err := redis.Get("nonexistent_key") if err != nil { log.Printf("Error: %v", err) return } // Check for nil values (key doesn't exist) if value == nil { fmt.Println("Key doesn't exist") } else { fmt.Println("Value:", string(value)) } // Connection errors err = redis.Ping() if err != nil { log.Fatal("Connection lost:", err) } ``` -------------------------------- ### Redis Connection Pooling Configuration in Go Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Shows how to configure libredis for connection pooling by specifying parameters like network type, address, maximum idle connections, and timeouts. ```go config := &client.DialConfig{ Network: "tcp", Address: "localhost:6379", MaxIdle: 50, // Maximum idle connections Timeout: 10 * time.Second, // Connection timeout TCPKeepAlive: 30, // Keep-alive interval } redis, err := client.DialWithConfig(config) if err != nil { log.Fatal("Connection failed:", err) } ``` -------------------------------- ### Connect to Redis using URL Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Connects to Redis by parsing a connection URL. This method simplifies configuration by embedding network, authentication, and connection pool settings within a single string. ```go redis, err := client.DialURL("tcp://auth:password@127.0.0.1:6379/0?timeout=5s&maxidle=10") if err != nil { log.Fatal("Failed to connect:", err) } defer redis.Close() ``` -------------------------------- ### Redis Client Certificate Authentication in Go Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Shows how to configure libredis for SSL/TLS connections that require client certificate authentication, by providing paths to the client certificate, private key, and CA certificate. ```go config := &client.DialConfig{ Network: "tcp", Address: "redis.example.com:6380", SSL: true, SSLCert: "/path/to/client.crt", SSLKey: "/path/to/client.key", SSLCA: "/path/to/ca.crt", } ``` -------------------------------- ### Good: Proper Error Handling Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Shows the correct way to handle errors returned by Redis operations. It emphasizes checking for errors after each command and propagating them appropriately, often by wrapping them with context. ```go // ✅ Good: Proper error handling func setUserData(userID string, data map[string]string) error { err := redisClient.HMSet("user:"+userID, data) if err != nil { return fmt.Errorf("failed to save user data: %w", err) } return nil } ``` -------------------------------- ### Bad: Ignoring Errors Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Highlights the danger of ignoring errors from Redis operations. Unhandled errors can lead to unexpected behavior, data corruption, or application instability. ```go // ❌ Bad: Ignoring errors func badExample() { redisClient.Set("key", "value") // Don't ignore errors } ``` -------------------------------- ### Redis Geospatial Operations in Go Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Demonstrates how to use libredis for geospatial operations, including adding locations, calculating distances, searching nearby points, and retrieving coordinates. Requires Redis 3.2+ for most operations and 6.2+ for modern search. ```go // Add locations to a geospatial index locations := []client.GeoMember{ {Longitude: -122.4194, Latitude: 37.7749, Member: "San Francisco"}, {Longitude: -74.0060, Latitude: 40.7128, Member: "New York"}, {Longitude: -87.6298, Latitude: 41.8781, Member: "Chicago"}, {Longitude: 2.3522, Latitude: 48.8566, Member: "Paris"}, } count, err := redis.GeoAdd("cities", locations) if err != nil { log.Fatal("GeoAdd failed:", err) } fmt.Printf("Added %d cities\n", count) // Calculate distance between cities distance, err := redis.GeoDist("cities", "San Francisco", "New York") if err != nil { log.Fatal("GeoDist failed:", err) } fmt.Printf("Distance SF to NYC: %.2f meters\n", distance) // Distance with specific unit distanceKM, err := redis.GeoDistWithUnit("cities", "San Francisco", "New York", "km") if err != nil { log.Fatal("GeoDistWithUnit failed:", err) } fmt.Printf("Distance SF to NYC: %.2f km\n", distanceKM) // Find nearby locations (modern search - Redis 6.2+) searchOpts := client.GeoSearchOptions{ FromLonLat: &client.GeoCoordinate{ Longitude: -122.4194, Latitude: 37.7749, }, ByRadius: &client.GeoRadius{ Radius: 1000, Unit: "km", }, WithCoord: true, WithDist: true, Count: 5, } nearbyLocations, err := redis.GeoSearch("cities", searchOpts) if err != nil { log.Fatal("GeoSearch failed:", err) } fmt.Println("Nearby locations:") for _, location := range nearbyLocations { fmt.Printf(" %s", location.Member) if location.Distance != nil { fmt.Printf(" (%.2f km)", *location.Distance) } if location.Coordinates != nil { fmt.Printf(" [%.4f, %.4f]", location.Coordinates.Longitude, location.Coordinates.Latitude) } fmt.Println() } // Get coordinates of specific locations coords, err := redis.GeoPos("cities", "San Francisco", "Paris") if err != nil { log.Fatal("GeoPos failed:", err) } for i, coord := range coords { if coord != nil { cities := []string{"San Francisco", "Paris"} fmt.Printf("%s: [%.4f, %.4f]\n", cities[i], coord.Longitude, coord.Latitude) } } ``` -------------------------------- ### Redis List Operations Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Shows fundamental Redis list operations: LPUSH for adding elements to the head of a list, LRange for retrieving a range of elements, and LPop for removing and returning the first element from a list. ```go // Push items to list length, err := redis.LPush("tasks", "task1", "task2", "task3") if err != nil { log.Fatal("LPush failed:", err) } fmt.Println("List length:", length) // Get list items items, err := redis.LRange("tasks", 0, -1) if err != nil { log.Fatal("LRange failed:", err) } fmt.Println("Tasks:", items) // Pop items from list item, err := redis.LPop("tasks") if err != nil { log.Fatal("LPop failed:", err) } if item != nil { fmt.Println("Popped task:", string(item)) } ``` -------------------------------- ### Go: Store and Find Nearby Locations with Redis Geospatial Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Shows how to add locations to a Redis geospatial index using `GeoAdd` and query for nearby points using `GeoSearch` with radius and distance options. ```go // Store and find nearby locations func findNearbyStores(userLat, userLon float64, radiusKM float64) ([]string, error) { // Add stores to geospatial index (typically done during setup) stores := []client.GeoMember{ {Longitude: -122.4194, Latitude: 37.7749, Member: "Downtown Store"}, {Longitude: -122.4094, Latitude: 37.7849, Member: "Marina Store"}, {Longitude: -122.4294, Latitude: 37.7649, Member: "Mission Store"}, } redisClient.GeoAdd("stores", stores) // Search for nearby stores searchOpts := client.GeoSearchOptions{ FromLonLat: &client.GeoCoordinate{ Longitude: userLon, Latitude: userLat, }, ByRadius: &client.GeoRadius{ Radius: radiusKM, Unit: "km", }, WithDist: true, Count: 10, } locations, err := redisClient.GeoSearch("stores", searchOpts) if err != nil { return nil, err } var nearbyStores []string for _, location := range locations { distance := *location.Distance nearbyStores = append(nearbyStores, fmt.Sprintf("%s (%.2f km)", location.Member, distance)) } return nearbyStores, nil } // Delivery tracking func trackDelivery(driverID string, lat, lon float64) error { driver := client.GeoMember{ Longitude: lon, Latitude: lat, Member: driverID, } _, err := redisClient.GeoAdd("drivers", []client.GeoMember{driver}) return err } func findNearestDriver(customerLat, customerLon float64) (string, float64, error) { searchOpts := client.GeoSearchOptions{ FromLonLat: &client.GeoCoordinate{ Longitude: customerLon, Latitude: customerLat, }, ByRadius: &client.GeoRadius{ Radius: 50, // 50 km search radius Unit: "km", }, WithDist: true, Count: 1, } drivers, err := redisClient.GeoSearch("drivers", searchOpts) if err != nil { return "", 0, err } if len(drivers) == 0 { return "", 0, fmt.Errorf("no drivers found nearby") } nearest := drivers[0] return nearest.Member, *nearest.Distance, nil } ``` -------------------------------- ### Consumer Group Operations Example Source: https://github.com/therealbill/libredis/blob/master/doc/commands.md Illustrates setting up and reading from Redis consumer groups using `XGroupCreate` and `XReadGroup`, followed by acknowledging messages with `XAck`. ```go // Consumer groups redis.XGroupCreate("events", "processors", "$") streams := map[string]string{"events": ">"} messages, _ := redis.XReadGroup("processors", "worker1", streams) // Acknowledge processing redis.XAck("events", "processors", id) ``` -------------------------------- ### DialConfig Structure Definition Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Defines the structure used for configuring Redis client connections. It encompasses network type, address, authentication credentials, timeouts, and connection pooling parameters. ```APIDOC type DialConfig struct { Network string // "tcp" or "unix" Address string // "host:port" or "/path/to/socket" Database int // Redis database number Password string // Redis password Timeout time.Duration // Connection timeout MaxIdle int // Max idle connections in pool SSL bool // Enable SSL/TLS SSLSkipVerify bool // Skip SSL certificate verification SSLCert string // SSL certificate file path SSLKey string // SSL private key file path SSLCA string // SSL CA certificate file path TCPKeepAlive int // TCP keep-alive interval (seconds) } ``` -------------------------------- ### Redis Sorted Set Operations in Go Source: https://github.com/therealbill/libredis/blob/master/doc/getting-started.md Illustrates adding scored members to a Redis sorted set, including adding single members and multiple members with scores, and retrieving members in reverse order using the Go client library. Includes error handling. ```go // Add scored members count, err := redis.ZAdd("leaderboard", 100, "player1") if err != nil { log.Fatal("ZAdd failed:", err) } // Add multiple members scores := map[string]float64{ "player2": 150, "player3": 75, } count, err = redis.ZAddVariadic("leaderboard", scores) if err != nil { log.Fatal("ZAddVariadic failed:", err) } // Get top players topPlayers, err := redis.ZRevRange("leaderboard", 0, 2, true) if err != nil { log.Fatal("ZRevRange failed:", err) } fmt.Println("Top players:", topPlayers) ``` -------------------------------- ### Modern Geospatial Search Example Source: https://github.com/therealbill/libredis/blob/master/doc/commands.md Demonstrates using `GeoSearch` with options to find locations within a specified radius, including returning coordinates and distances. ```go // Modern radius search opts := client.GeoSearchOptions{ FromLonLat: &client.GeoCoordinate{Longitude: -122.4194, Latitude: 37.7749}, ByRadius: &client.GeoRadius{Radius: 50, Unit: client.GeoUnitKilometers}, WithCoord: true, WithDist: true, } locations, _ := redis.GeoSearch("cities", opts) ``` -------------------------------- ### Basic Geospatial Operations Example Source: https://github.com/therealbill/libredis/blob/master/doc/commands.md Shows how to add location data using `GeoAdd` and calculate distances between members using `GeoDist`. ```go // Adding locations members := []client.GeoMember{ {Longitude: -122.4194, Latitude: 37.7749, Member: "San Francisco"}, {Longitude: -74.0060, Latitude: 40.7128, Member: "New York"}, } redis.GeoAdd("cities", members) // Distance calculation dist, _ := redis.GeoDist("cities", "San Francisco", "New York") ``` -------------------------------- ### Redis String Commands (Basic) Source: https://github.com/therealbill/libredis/blob/master/doc/commands.md Reference for basic Redis string commands and their corresponding LibRedis Go client methods, including GET, SET, APPEND, STRLEN, GETSET, and SETNX. ```APIDOC GET key Method: Get(key) Description: Gets string value as bytes. SET key value Method: Set(key, value) Description: Sets string value. APPEND key value Method: Append(key, value) Description: Appends value to string, returns new length. STRLEN key Method: StrLen(key) Description: Returns string length. GETSET key value Method: GetSet(key, value) Description: Atomically sets and returns old value. SETNX key value Method: Setnx(key, value) Description: Sets only if key doesn't exist. ``` -------------------------------- ### Go Test and Benchmark Commands Source: https://github.com/therealbill/libredis/blob/master/README.md Provides standard Go commands for running tests, generating code coverage reports, and executing benchmarks for the libredis project. ```go normal test: go test coverage test: go test -cover coverage test with html result: go test -coverprofile=cover.out go tool cover -html=cover.out Running Benchmarks: go test -test.run=none -test.bench="Benchmark.*" ``` -------------------------------- ### Go: Advanced Pipelining Patterns with LibRedis Source: https://github.com/therealbill/libredis/blob/master/doc/advanced-features.md Illustrates advanced pipelining techniques in LibRedis, including bulk data insertion and batch operations with mixed command types. The `bulkInsert` function shows how to efficiently insert multiple key-value pairs, while `batchOperations` demonstrates executing diverse commands like list pushes, set additions, hash updates, and counter increments within a single pipeline. Error handling for individual command failures within the pipeline is also shown. ```go // Bulk data insertion func bulkInsert(redis *client.Redis, data map[string]string) error { pipeline := redis.Pipelining() defer pipeline.Close() // Send all SET commands for key, value := range data { pipeline.Command("SET", key, value) } // Execute all commands responses, err := pipeline.ReceiveAll() if err != nil { return fmt.Errorf("bulk insert failed: %w", err) } // Check for errors in responses for i, response := range responses { if response.Type == client.ErrorReply { return fmt.Errorf("command %d failed: %s", i, response.Error) } } return nil } // Batch operations with mixed commands func batchOperations(redis *client.Redis) error { pipeline := redis.Pipelining() defer pipeline.Close() // Mix different types of operations pipeline.Command("LPUSH", "queue", "task1", "task2") pipeline.Command("SADD", "tags", "important", "urgent") pipeline.Command("HSET", "user:1", "last_seen", "2023-01-01") pipeline.Command("INCR", "visits") responses, err := pipeline.ReceiveAll() if err != nil { return err } fmt.Printf("Queue length: %v\n", responses[0]) fmt.Printf("Tags added: %v\n", responses[1]) fmt.Printf("Hash set: %v\n", responses[2]) fmt.Printf("Visit count: %v\n", responses[3]) return nil } ``` -------------------------------- ### Hash Operations Source: https://github.com/therealbill/libredis/blob/master/doc/commands.md Operations for managing fields and values within Redis Hash data structures. Includes setting multiple fields, retrieving multiple values, getting all fields/values, and getting field names or values. ```APIDOC Hash Operations: HMSET key field value [field value ...] Method: HMSet(key, pairs) Description: Sets multiple fields in a hash. HMGET key field [field ...] Method: HMGet(key, fields...) Description: Gets the values of multiple fields in a hash. HGETALL key Method: HGetAll(key) Description: Gets all fields and values in a hash. HKEYS key Method: HKeys(key) Description: Gets all field names in a hash. HVALS key Method: HVals(key) Description: Gets all values in a hash. HINCRBY key field increment Method: HIncrBy(key, field, increment) Description: Increments the integer value of a field by the specified amount. HINCRBYFLOAT key field increment Method: HIncrByFloat(key, field, increment) Description: Increments the float value of a field by the specified amount. HSTRLEN key field Method: HStrLen(key, field) Description: Returns the length of the string value stored at field in the hash stored at key. (Redis 3.2+) HRANDFIELD key [count] Method: HRandField(key) Description: Returns one or more random fields from the hash stored at key. (Redis 6.2+) ``` -------------------------------- ### Go: Basic Pipelining with LibRedis Source: https://github.com/therealbill/libredis/blob/master/doc/advanced-features.md Demonstrates how to use LibRedis pipelining to send multiple commands to Redis efficiently without waiting for individual responses. This method significantly improves performance for bulk operations by reducing network round trips. It requires a Redis client instance and uses `Pipelining()` to create a pipeline, `Command()` to queue operations, and `ReceiveAll()` to fetch all results. ```go package main import ( "fmt" "log" "github.com/therealbill/libredis/client" ) func main() { redis, err := client.DialWithConfig(&client.DialConfig{ Network: "tcp", Address: "localhost:6379", }) if err != nil { log.Fatal(err) } defer redis.Close() // Create pipeline pipeline := redis.Pipelining() defer pipeline.Close() // Send multiple commands pipeline.Command("SET", "key1", "value1") pipeline.Command("SET", "key2", "value2") pipeline.Command("INCR", "counter") pipeline.Command("GET", "key1") // Receive all responses at once responses, err := pipeline.ReceiveAll() if err != nil { log.Fatal("Pipeline failed:", err) } // Process responses for i, response := range responses { fmt.Printf("Response %d: %v\n", i, response) } } ``` -------------------------------- ### Redis Configuration Commands Source: https://github.com/therealbill/libredis/blob/master/doc/commands.md Allows retrieval and modification of Redis server configuration parameters. Supports getting, setting, rewriting, and resetting configuration settings. ```APIDOC Configuration Commands: CONFIG GET parameter - Gets the value of a configuration parameter. - Method: ConfigGet(parameter string) CONFIG SET parameter value - Sets the value of a configuration parameter. - Method: ConfigSet(parameter string, value string) CONFIG REWRITE - Rewrites the configuration file by saving the current configuration. - Method: ConfigRewrite() CONFIG RESETSTAT - Resets the server's statistics. - Method: ConfigResetStat() ``` -------------------------------- ### Redis Basic String Operations Source: https://github.com/therealbill/libredis/blob/master/doc/commands.md Demonstrates fundamental string operations in libredis, including setting a key-value pair and retrieving the value associated with a key. ```go // String operations redis.Set("key", "value") value, _ := redis.Get("key") ``` -------------------------------- ### Hash Operations Source: https://github.com/therealbill/libredis/blob/master/doc/commands.md Documentation for Redis Hash operations, including setting and getting field-value pairs, checking field existence, deleting fields, and retrieving hash length. ```APIDOC Hash Operations: Basic Hash Operations: HSet(key, field, value) - Sets the string value of a field in a hash stored at key. - Parameters: - key: The key of the hash. - field: The field to set. - value: The value to set for the field. - Returns: The number of fields that were added. HGet(key, field) - Gets the value of a field in a hash stored at key. - Parameters: - key: The key of the hash. - field: The field whose value to retrieve. - Returns: The value of the field, or nil if the field or key does not exist. HExists(key, field) - Checks if a field exists in a hash stored at key. - Parameters: - key: The key of the hash. - field: The field to check. - Returns: True if the field exists, false otherwise. HDel(key, fields...) - Removes one or more fields from a hash stored at key. - Parameters: - key: The key of the hash. - fields: The fields to remove. - Returns: The number of fields that were removed. HLen(key) - Gets the number of fields in a hash stored at key. - Parameters: - key: The key of the hash. - Returns: The number of fields in the hash. HSetnx(key, field, value) - Sets the value of a field in a hash stored at key, only if the field does not exist. - Parameters: - key: The key of the hash. - field: The field to set. - value: The value to set for the field. - Returns: True if the field was set, false otherwise. ``` -------------------------------- ### Redis Hash Operations Source: https://github.com/therealbill/libredis/blob/master/doc/api-reference.md Documentation for Redis Hash operations, covering setting and getting single fields, multiple fields, all fields, string length, and random fields. ```APIDOC HSet key field value Sets a field and its value in a hash. Parameters: key: The hash key. field: The field name. value: The field value. Returns: true if the field is new, false if it was updated (bool). HGet key field Gets a field value from a hash. Parameters: key: The hash key. field: The field name. Returns: The field value as a byte slice ([]byte). HMSet key pairs Sets multiple fields and their values in a hash. Parameters: key: The hash key. pairs: A map where keys are field names (string) and values are field values (string). Returns: An error if the operation fails. HGetAll key Gets all field-value pairs from a hash. Parameters: key: The hash key. Returns: A map of all fields and values (map[string]string). HStrLen key field Gets the string length of a field's value in a hash. Parameters: key: The hash key. field: The field name. Returns: The length of the string value (int64). HRandField key Returns a random field from a hash. Parameters: key: The hash key. Returns: A random field name (string). ``` -------------------------------- ### Go: Basic Lua Scripting Source: https://github.com/therealbill/libredis/blob/master/doc/advanced-features.md Demonstrates loading and executing a simple Lua script on Redis. The script sets a key-value pair and retrieves the value. It shows how to use ScriptLoad for SHA1 caching and EvalSha for execution. ```go // Load and execute Lua script func basicLuaScript(redis *client.Redis) error { script := ` local key = KEYS[1] local value = ARGV[1] redis.call('SET', key, value) local result = redis.call('GET', key) return result ` // Load script and get SHA1 sha1, err := redis.ScriptLoad(script) if err != nil { return err } // Execute by SHA1 result, err := redis.EvalSha(sha1, []string{"mykey"}, []string{"myvalue"}) if err != nil { return err } fmt.Printf("Script result: %v\n", result) return nil } ``` -------------------------------- ### Go: Efficient Bulk Operations with LibRedis Pipelining Source: https://github.com/therealbill/libredis/blob/master/doc/advanced-features.md Demonstrates efficient bulk operations using LibRedis pipelining. It batches commands to reduce network latency and improve throughput, with a configurable batch size for optimal performance. Requires a Redis client instance and a data source. ```go func efficientBulkOperations(redis *client.Redis) error { // Use pipelining for bulk operations pipeline := redis.Pipelining() defer pipeline.Close() // Batch size optimization batchSize := 1000 data := generateTestData(10000) // Your data source for i := 0; i < len(data); i += batchSize { end := i + batchSize if end > len(data) { end = len(data) } // Send batch for j := i; j < end; j++ { pipeline.Command("SET", data[j].Key, data[j].Value) } // Execute batch _, err := pipeline.ReceiveAll() if err != nil { return fmt.Errorf("batch %d failed: %w", i/batchSize, err) } } return nil } ```