redis

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 30, 2026 License: MIT Imports: 6 Imported by: 0

README

Redis - Go-Redis Wrapper

A lightweight wrapper around go-redis with helper methods for caching and connection handling. Provides a simple, idiomatic API for Redis operations including strings, hashes, lists, sets, sorted sets, and JSON serialization.

Installation

go get github.com/davidsugianto/go-pkgs/redis

You'll also need to add the go-redis dependency:

go get github.com/redis/go-redis/v9

Quick Start

package main

import (
    "context"
    "github.com/davidsugianto/go-pkgs/redis"
)

func main() {
    // Create a new Redis client
    client := redis.New("localhost:6379")
    defer client.Close()

    ctx := context.Background()
    
    // Basic operations
    client.Set(ctx, "key", "value", time.Hour)
    val, _ := client.Get(ctx, "key")
    
    // JSON operations
    user := User{Name: "John"}
    client.SetJSON(ctx, "user:1", user, time.Hour)
    client.GetJSON(ctx, "user:1", &user)
}

Features

  • Connection Management - Automatic connection pooling with configurable options
  • Type Safety - Helper methods with clear error handling
  • JSON Support - Built-in JSON serialization/deserialization
  • Atomic Operations - Support for SETNX, SETXX, and other atomic operations
  • Data Structures - Full support for strings, hashes, lists, sets, and sorted sets
  • Expiration - Easy key expiration and TTL management
  • Context Support - All operations support context for cancellation and timeouts
  • Connection Pool Stats - Monitor connection pool health

Client Configuration

Basic Setup
client := redis.New("localhost:6379")
With Options
client := redis.New("localhost:6379",
    redis.WithPassword("mypassword"),
    redis.WithDB(1),
    redis.WithPoolSize(20),
    redis.WithMinIdleConns(10),
    redis.WithTimeout(5*time.Second),
    redis.WithMaxRetries(3),
)
Available Options
  • WithPassword(password string) - Set Redis password
  • WithDB(db int) - Select database number (default: 0)
  • WithPoolSize(size int) - Connection pool size (default: 10)
  • WithMinIdleConns(conns int) - Minimum idle connections (default: 5)
  • WithTimeout(timeout time.Duration) - Dial, read, and write timeout (default: 5s)
  • WithMaxRetries(retries int) - Maximum retry attempts (default: 3)

Basic Operations

Connection Testing
err := client.Ping(ctx)
Set and Get
// Set a key
err := client.Set(ctx, "key", "value", time.Hour)

// Get a key
val, err := client.Get(ctx, "key")
if err == redis.ErrKeyNotFound {
    // Key doesn't exist
}

// Get as bytes
data, err := client.GetBytes(ctx, "key")
Delete and Exists
// Delete one or more keys
err := client.Delete(ctx, "key1", "key2", "key3")

// Check if key exists
exists, err := client.Exists(ctx, "key")
Expiration
// Set expiration
err := client.Expire(ctx, "key", 10*time.Second)

// Get TTL
ttl, err := client.TTL(ctx, "key")

JSON Operations

type User struct {
    ID    int    `json:"id"`
    Name  string `json:"name"`
    Email string `json:"email"`
}

// Store JSON
user := User{ID: 1, Name: "John"}
err := client.SetJSON(ctx, "user:1", user, time.Hour)

// Retrieve JSON
var user User
err := client.GetJSON(ctx, "user:1", &user)

Atomic Operations

Conditional Sets
// Set if key doesn't exist (useful for locking)
success, err := client.SetNX(ctx, "lock:resource", "locked", time.Minute)

// Set if key exists (useful for updates)
success, err := client.SetXX(ctx, "user:1", "updated", time.Hour)
Counters
// Increment
newVal, err := client.Increment(ctx, "counter", 1)  // Increment by 1
newVal, err := client.Increment(ctx, "counter", 5)  // Increment by 5

// Decrement
newVal, err := client.Decrement(ctx, "counter", 2)
Batch Operations
// Get multiple keys
values, err := client.MGet(ctx, "key1", "key2", "key3")

// Set multiple keys
err := client.MSet(ctx, "key1", "val1", "key2", "val2", "key3", "val3")

Hash Operations

// Set hash field
err := client.HSet(ctx, "user:1:profile", "name", "John")

// Get hash field
name, err := client.HGet(ctx, "user:1:profile", "name")

// Set multiple fields
err := client.HMSet(ctx, "user:1:profile", "name", "John", "age", "30", "city", "NYC")

// Get all fields
all, err := client.HGetAll(ctx, "user:1:profile")
// all is map[string]string

// Delete fields
err := client.HDel(ctx, "user:1:profile", "name", "age")

List Operations

// Push to list
err := client.LPush(ctx, "tasks", "task1", "task2")  // Push to left
err := client.RPush(ctx, "tasks", "task3", "task4")  // Push to right

// Pop from list
task, err := client.LPop(ctx, "tasks")  // Pop from left
task, err := client.RPop(ctx, "tasks")  // Pop from right

// Get list length
length, err := client.LLen(ctx, "tasks")

// Get range of items
items, err := client.LRange(ctx, "tasks", 0, -1)  // Get all
items, err := client.LRange(ctx, "tasks", 0, 2)   // Get first 3

Set Operations

// Add members
err := client.SAdd(ctx, "tags", "golang", "redis", "go-pkgs")

// Get all members
members, err := client.SMembers(ctx, "tags")

// Check membership
isMember, err := client.SIsMember(ctx, "tags", "golang")

// Remove members
err := client.SRem(ctx, "tags", "golang")

Sorted Set Operations

// Add with scores
err := client.ZAdd(ctx, "leaderboard",
    redis.Z{Score: 100, Member: "Alice"},
    redis.Z{Score: 200, Member: "Bob"},
    redis.Z{Score: 150, Member: "Charlie"},
)

// Get by index range
players, err := client.ZRange(ctx, "leaderboard", 0, -1)  // All players

// Get by score range
top, err := client.ZRangeByScore(ctx, "leaderboard", "150", "300")

// Remove members
err := client.ZRem(ctx, "leaderboard", "Alice")

Pattern Matching

// Get all keys matching pattern
keys, err := client.Keys(ctx, "user:*")

// Scan keys (safer for large datasets)
cursor := uint64(0)
for {
    keys, cursor, err := client.Scan(ctx, cursor, "user:*", 100)
    // Process keys
    if cursor == 0 {
        break
    }
}

Pub/Sub

// Publish message
err := client.Publish(ctx, "channel", "message")

// Subscribe
pubsub := client.Subscribe(ctx, "channel")
defer pubsub.Close()

// Receive messages
for msg := range pubsub.Channel() {
    fmt.Printf("Received: %s\n", msg.Payload)
}

Monitoring

Connection Pool Stats
stats := client.Stats()
fmt.Printf("Hits: %d\n", stats.Hits)
fmt.Printf("Misses: %d\n", stats.Misses)
fmt.Printf("Timeouts: %d\n", stats.Timeouts)

Error Handling

The package provides two common error types:

if err == redis.ErrKeyNotFound {
    // Key doesn't exist
}

if err == redis.ErrConnectionFailed {
    // Connection failed
}

Complete Example

package main

import (
    "context"
    "fmt"
    "time"
    
    "github.com/davidsugianto/go-pkgs/redis"
)

func main() {
    // Initialize client
    client := redis.New("localhost:6379")
    defer client.Close()

    ctx := context.Background()
    
    // Test connection
    if err := client.Ping(ctx); err != nil {
        panic(err)
    }
    
    // Basic operations
    client.Set(ctx, "greeting", "Hello, Redis!", time.Hour)
    val, _ := client.Get(ctx, "greeting")
    fmt.Println(val)
    
    // JSON operations
    user := User{ID: 1, Name: "John"}
    client.SetJSON(ctx, "user:1", user, time.Hour)
    var retrievedUser User
    client.GetJSON(ctx, "user:1", &retrievedUser)
    fmt.Printf("Retrieved: %+v\n", retrievedUser)
    
    // Hash operations
    client.HMSet(ctx, "user:1:profile",
        "name", "John Doe",
        "email", "john@example.com",
    )
    profile, _ := client.HGetAll(ctx, "user:1:profile")
    fmt.Printf("Profile: %+v\n", profile)
}

Advanced Usage

Using Context for Timeouts
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()

val, err := client.Get(ctx, "key")
Accessing Underlying Redis Client

The Client embeds *redis.Client, so you can access all go-redis functionality:

// Use any go-redis method directly
result := client.Pipeline()
result.Set(ctx, "key1", "val1", 0)
result.Get(ctx, "key1")
_, err := result.Exec(ctx)

Best Practices

  1. Always use context - Pass context to all operations for cancellation and timeouts
  2. Handle errors - Check for ErrKeyNotFound when getting values
  3. Close connections - Always call client.Close() when done
  4. Use connection pooling - Configure pool size based on your workload
  5. Set appropriate timeouts - Configure timeouts to prevent hanging connections
  6. Use JSON for complex data - Use SetJSON/GetJSON for structured data
  7. Use atomic operations - Use SetNX for distributed locking
  8. Monitor pool stats - Track connection pool statistics in production

Examples

See the example/ directory for a complete working example:

# Start Redis (if not already running)
docker run -d -p 6379:6379 redis:latest

# Run example
cd example
go run main.go

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrKeyNotFound indicates a key does not exist in Redis
	ErrKeyNotFound = errors.New("key not found")

	// ErrConnectionFailed indicates a failed connection attempt
	ErrConnectionFailed = errors.New("connection failed")
)

Functions

This section is empty.

Types

type Client

type Client struct {
	*redis.Client
}

Client wraps the go-redis client with helper methods

func New

func New(addr string, opts ...Option) *Client

New creates a new Redis client with default options

func (*Client) Close

func (c *Client) Close() error

Close closes the Redis connection

func (*Client) Decrement

func (c *Client) Decrement(ctx context.Context, key string, value int64) (int64, error)

Decrement decrements the value of a key by the specified amount

func (*Client) Delete

func (c *Client) Delete(ctx context.Context, keys ...string) error

Delete removes one or more keys

func (*Client) Exists

func (c *Client) Exists(ctx context.Context, keys ...string) (bool, error)

Exists checks if one or more keys exist

func (*Client) Expire

func (c *Client) Expire(ctx context.Context, key string, expiration time.Duration) error

Expire sets a key's expiration time

func (*Client) Get

func (c *Client) Get(ctx context.Context, key string) (string, error)

Get retrieves a value by key (returns ErrKeyNotFound if key doesn't exist)

func (*Client) GetBytes

func (c *Client) GetBytes(ctx context.Context, key string) ([]byte, error)

GetBytes retrieves a value as bytes by key

func (*Client) GetJSON

func (c *Client) GetJSON(ctx context.Context, key string, dest interface{}) error

GetJSON retrieves and unmarshals a JSON value into the provided type

func (*Client) HDel

func (c *Client) HDel(ctx context.Context, key string, fields ...string) error

HDel deletes one or more fields from a hash

func (*Client) HGet

func (c *Client) HGet(ctx context.Context, key string, field string) (string, error)

HGet retrieves a field from a hash

func (*Client) HGetAll

func (c *Client) HGetAll(ctx context.Context, key string) (map[string]string, error)

HGetAll retrieves all fields from a hash

func (*Client) HMSet

func (c *Client) HMSet(ctx context.Context, key string, pairs ...interface{}) error

HMSet sets multiple fields in a hash at once

func (*Client) HSet

func (c *Client) HSet(ctx context.Context, key string, field string, value interface{}) error

HSet sets a field in a hash

func (*Client) Increment

func (c *Client) Increment(ctx context.Context, key string, value int64) (int64, error)

Increment increments the value of a key by the specified amount

func (*Client) Keys

func (c *Client) Keys(ctx context.Context, pattern string) ([]string, error)

Keys finds all keys matching a pattern

func (*Client) LLen

func (c *Client) LLen(ctx context.Context, key string) (int64, error)

LLen returns the length of a list

func (*Client) LPop

func (c *Client) LPop(ctx context.Context, key string) (string, error)

LPop removes and returns the first element of a list

func (*Client) LPush

func (c *Client) LPush(ctx context.Context, key string, values ...interface{}) error

LPush prepends one or more values to a list

func (*Client) LRange

func (c *Client) LRange(ctx context.Context, key string, start, stop int64) ([]string, error)

LRange returns elements from a list

func (*Client) MGet

func (c *Client) MGet(ctx context.Context, keys ...string) ([]interface{}, error)

MGet retrieves multiple values at once

func (*Client) MSet

func (c *Client) MSet(ctx context.Context, pairs ...interface{}) error

MSet sets multiple key-value pairs at once

func (*Client) Ping

func (c *Client) Ping(ctx context.Context) error

Ping checks the Redis connection

func (*Client) Publish

func (c *Client) Publish(ctx context.Context, channel string, message interface{}) error

Publish publishes a message to a channel

func (*Client) RPop

func (c *Client) RPop(ctx context.Context, key string) (string, error)

RPop removes and returns the last element of a list

func (*Client) RPush

func (c *Client) RPush(ctx context.Context, key string, values ...interface{}) error

RPush appends one or more values to a list

func (*Client) SAdd

func (c *Client) SAdd(ctx context.Context, key string, members ...interface{}) error

SAdd adds one or more members to a set

func (*Client) SIsMember

func (c *Client) SIsMember(ctx context.Context, key string, member interface{}) (bool, error)

SIsMember checks if a value is a member of a set

func (*Client) SMembers

func (c *Client) SMembers(ctx context.Context, key string) ([]string, error)

SMembers returns all members of a set

func (*Client) SRem

func (c *Client) SRem(ctx context.Context, key string, members ...interface{}) error

SRem removes one or more members from a set

func (*Client) Scan

func (c *Client) Scan(ctx context.Context, cursor uint64, match string, count int64) ([]string, uint64, error)

Scan iterates over keys matching a pattern (safer than Keys for large datasets)

func (*Client) Set

func (c *Client) Set(ctx context.Context, key string, value interface{}, expiration time.Duration) error

Set stores a key-value pair with expiration

func (*Client) SetJSON

func (c *Client) SetJSON(ctx context.Context, key string, value interface{}, expiration time.Duration) error

SetJSON stores a JSON-serialized value with expiration

func (*Client) SetNX

func (c *Client) SetNX(ctx context.Context, key string, value interface{}, expiration time.Duration) (bool, error)

SetNX sets a key only if it doesn't already exist (atomic operation)

func (*Client) SetXX

func (c *Client) SetXX(ctx context.Context, key string, value interface{}, expiration time.Duration) (bool, error)

SetXX sets a key only if it already exists (atomic operation)

func (*Client) Stats

func (c *Client) Stats() *redis.PoolStats

Stats returns connection pool statistics

func (*Client) Subscribe

func (c *Client) Subscribe(ctx context.Context, channels ...string) *redis.PubSub

Subscribe subscribes to one or more channels

func (*Client) TTL

func (c *Client) TTL(ctx context.Context, key string) (time.Duration, error)

TTL returns the remaining time to live of a key

func (*Client) ZAdd

func (c *Client) ZAdd(ctx context.Context, key string, members ...redis.Z) error

ZAdd adds one or more members with scores to a sorted set

func (*Client) ZRange

func (c *Client) ZRange(ctx context.Context, key string, start, stop int64) ([]string, error)

ZRange returns elements from a sorted set by index range

func (*Client) ZRangeByScore

func (c *Client) ZRangeByScore(ctx context.Context, key string, min, max string) ([]string, error)

ZRangeByScore returns elements from a sorted set by score range

func (*Client) ZRem

func (c *Client) ZRem(ctx context.Context, key string, members ...interface{}) error

ZRem removes one or more members from a sorted set

type Option

type Option func(*redis.Options)

Option configures the Redis client

func WithDB

func WithDB(db int) Option

WithDB sets the Redis database number

func WithMaxRetries

func WithMaxRetries(retries int) Option

WithMaxRetries sets the maximum number of retries

func WithMinIdleConns

func WithMinIdleConns(conns int) Option

WithMinIdleConns sets the minimum idle connections

func WithPassword

func WithPassword(password string) Option

WithPassword sets the Redis password

func WithPoolSize

func WithPoolSize(size int) Option

WithPoolSize sets the connection pool size

func WithTimeout

func WithTimeout(timeout time.Duration) Option

WithTimeout sets dial, read, and write timeouts

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL