Mastering Go Redis List Operations: Practical API Usage and Performance Benchmark

This article walks through practical Go implementations of Redis list commands—including LPush, RPush, LLen, LRange, and others—provides unit test examples, demonstrates a simple performance benchmark, and shares a reusable wrapper library for streamlined backend development.

FunTester
FunTester
FunTester
Mastering Go Redis List Operations: Practical API Usage and Performance Benchmark

Basic List Operations (LPush, RPush, LPop, RPop)

The article begins with simple unit tests that verify the core list commands. Example test functions create a Redis pool, push a value, pop it, and assert equality.

func TestPushPop(t *testing.T) {
    var pool = redis.NewRdisPool("127.0.0.1:6379", base.Empty, 1)
    var key = "fun"
    var value = "abc"
    pool.LPush(key, value)
    pop := pool.LPop(key)
    assert.Equal(t, pop, value)
}

func TestPushPop2(t *testing.T) {
    var pool = redis.NewRdisPool("127.0.0.1:6379", base.Empty, 1)
    var key = "fun"
    var value = "abc"
    pool.RPush(key, value)
    pop := pool.RPop(key)
    assert.Equal(t, pop, value)
}

Length Retrieval (LLen)

A test case demonstrates how to obtain the length of a list before and after push/pop operations, confirming that the length changes as expected.

func TestLen(t *testing.T) {
    var pool = redis.NewRdisPool("127.0.0.1:6379", base.Empty, 1)
    var key = "fun"
    var value = "FunTester"
    len1 := pool.LLen(key)
    pool.LPush(key, value)
    len2 := pool.LLen(key)
    pool.LPop(key)
    len3 := pool.LLen(key)
    assert.Equal(t, len1, len3)
    assert.Equal(t, len1, len2-1)
}

Range Query (LRange)

The article shows how to retrieve a subset of list elements without removing them, using a loop to push ten items and then fetching indices 1‑3.

func TestLRange(t *testing.T) {
    var pool = redis.NewRdisPool("127.0.0.1:6379", base.Empty, 1)
    var key = "fun"
    var value = "FunTester"
    pool.Del(key)
    for i := 0; i < 10; i++ {
        pool.RPush(key, value+strconv.Itoa(i))
    }
    lRange := pool.LRange(key, 1, 3)
    for _, s := range lRange {
        log.Println(s)
    }
}

Sample console output confirms the correct slice of values.

Performance Test

A single benchmark measures the combined cost of a push and a pop over a 20‑second window, reporting total requests and QPS (≈26,600). The test uses execute.ExecuteRoutineTime to run the operations concurrently.

func TestPushPopPerf(t *testing.T) {
    var pool = redis.NewRdisPool("127.0.0.1:6379", base.Empty, 1)
    var key = "fun"
    var value = "FunTester"
    execute.ExecuteRoutineTime(func() {
        pool.LPush(key, value)
        pool.RPop(key)
    }, 20, 2)
}

Reusable API Wrapper

The author provides a Go package that encapsulates the Redis list commands with error handling and logging. Each method returns the raw result type (e.g., int64 for push/pop counts) or a sentinel error value from the base package.

package redis

import (
    "funtester/base"
    "log"
)

// LPush inserts a value at the left end of the list.
func (r RedisBase) LPush(key string, value interface{}) int64 {
    result, err := r.pool.LPush(key, value).Result()
    if err != nil {
        log.Printf("LPush:%s value: %s failed
", key, value)
        log.Println(err)
        return base.TestError
    }
    return result
}

// RPush inserts a value at the right end of the list.
func (r RedisBase) RPush(key string, value interface{}) int64 {
    result, err := r.pool.RPush(key, value).Result()
    if err != nil {
        log.Printf("RPush:%s value: %s failed
", key, value)
        log.Println(err)
        return base.TestError
    }
    return result
}

// LPop removes and returns the leftmost element.
func (r RedisBase) LPop(key string) string {
    result, err := r.pool.LPop(key).Result()
    if err != nil {
        log.Printf("LPop:%s failed
", key)
        log.Println(err)
        return base.Empty
    }
    return result
}

// RPop removes and returns the rightmost element.
func (r RedisBase) RPop(key string) string {
    result, err := r.pool.RPop(key).Result()
    if err != nil {
        log.Printf("RPop:%s failed
", key)
        log.Println(err)
        return base.Empty
    }
    return result
}

// LLen returns the length of the list.
func (r RedisBase) LLen(key string) int64 {
    result, err := r.pool.LLen(key).Result()
    if err != nil {
        log.Printf("LLen:%s failed
", key)
        log.Println(err)
        return base.TestError
    }
    return result
}

// LRange returns a slice of elements between start and end.
func (r RedisBase) LRange(key string, start, end int64) []string {
    result, err := r.pool.LRange(key, start, end).Result()
    if err != nil {
        log.Printf("LRange:%s failed
", key)
        log.Println(err)
        return nil
    }
    return result
}

// LRem removes elements matching a value with a count control.
func (r RedisBase) LRem(key string, count int64, value interface{}) int64 {
    result, err := r.pool.LRem(key, count, value).Result()
    if err != nil {
        log.Printf("LRem:%s count:%d value:%s failed
", key, count, value)
        log.Println(err)
        return base.TestError
    }
    return result
}

// LIndex fetches an element by its zero‑based index.
func (r RedisBase) LIndex(key string, index int64) string {
    result, err := r.pool.LIndex(key, index).Result()
    if err != nil {
        log.Printf("LIndex:%s index:%d failed
", key, index)
        log.Println(err)
        return base.Empty
    }
    return result
}

// LInsertBefore inserts a value before a pivot element.
func (r RedisBase) LInsertBefore(key string, pivot, value interface{}) int64 {
    result, err := r.pool.LInsertBefore(key, pivot, value).Result()
    if err != nil {
        log.Printf("LInsertBefore:%s pivot:%s value:%s failed
", key, pivot, value)
        log.Println(err)
        return base.TestError
    }
    return result
}

// LInsertAfter inserts a value after a pivot element.
func (r RedisBase) LInsertAfter(key string, pivot, value interface{}) int64 {
    result, err := r.pool.LInsertAfter(key, pivot, value).Result()
    if err != nil {
        log.Printf("LInsertAfter:%s pivot:%s value:%s failed
", key, pivot, value)
        log.Println(err)
        return base.TestError
    }
    return result
}

The wrapper can be imported into other Go projects to simplify Redis list manipulation while providing consistent logging and error handling.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Backend DevelopmentredisGoPerformance TestingAPIList
FunTester
Written by

FunTester

10k followers, 1k articles | completely useless

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.