[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-20":3},{"id":4,"title":5,"title_en":6,"abstract":5,"abstract_en":6,"content":7,"content_en":8,"category":9,"banner_id":10,"banner_path":11,"tags":12,"is_recommend":14,"prev_article":15,"next_article":19,"created_at":23},20,"Redis实战指南：从基础概念到Go语言应用","Redis Practical Guide: From Basic Concepts to Go Language Applications","### Redis实战指南：从基础概念到Go语言应用\n\n> Redis（Remote Dictionary Server）是一个开源的内存数据结构存储系统，它不仅可以用作数据库、缓存和消息代理，还支持多种数据结构，如字符串、哈希、列表、集合和有序集合等。今天我们将通过实际的Go语言代码示例来深入了解Redis的使用。\n\n#### Redis基础数据结构及操作\n\n##### 1. 字符串（String）\n\n字符串是Redis最基本的数据类型，可以存储文本、数字或二进制数据。\n\n```GO\npackage main\n\nimport (\n    \"context\"\n    \"fmt\"\n    \"time\"\n    \"github.com\u002Fgo-redis\u002Fredis\u002Fv8\"\n)\n\nvar ctx = context.Background()\nvar rdb *redis.Client\n\nfunc init() {\n    rdb = redis.NewClient(&redis.Options{\n        Addr:     \"localhost:6379\",\n        Password: \"\", \u002F\u002F no password set\n        DB:       0,  \u002F\u002F use default DB\n    })\n}\n\nfunc stringOperations() {\n    \u002F\u002F 设置键值对\n    err := rdb.Set(ctx, \"name\", \"Redis\", 0).Err()\n    if err != nil {\n        panic(err)\n    }\n\n    \u002F\u002F 获取键值\n    val, err := rdb.Get(ctx, \"name\").Result()\n    if err != nil {\n        panic(err)\n    }\n    fmt.Println(\"name:\", val)\n\n    \u002F\u002F 设置带过期时间的键值对\n    err = rdb.Set(ctx, \"counter\", 0, 1*time.Hour).Err()\n    if err != nil {\n        panic(err)\n    }\n\n    \u002F\u002F 自增操作\n    err = rdb.Incr(ctx, \"counter\").Err()\n    if err != nil {\n        panic(err)\n    }\n\n    val, err = rdb.Get(ctx, \"counter\").Result()\n    if err != nil {\n        panic(err)\n    }\n    fmt.Println(\"counter:\", val)\n}\n\n```\n##### 2. 哈希（Hash）\n\n哈希允许我们将多个键值对存储在一个键下，非常适合存储对象。\n\n\n```GO\nfunc hashOperations() {\n    \u002F\u002F 设置哈希字段\n    err := rdb.HSet(ctx, \"user:1000\", \"name\", \"张三\").Err()\n    if err != nil {\n        panic(err)\n    }\n    \n    err = rdb.HSet(ctx, \"user:1000\", \"email\", \"zhangsan@example.com\").Err()\n    if err != nil {\n        panic(err)\n    }\n\n    \u002F\u002F 获取单个字段\n    name, err := rdb.HGet(ctx, \"user:1000\", \"name\").Result()\n    if err != nil {\n        panic(err)\n    }\n    fmt.Println(\"user name:\", name)\n\n    \u002F\u002F 获取所有字段\n    userMap, err := rdb.HGetAll(ctx, \"user:1000\").Result()\n    if err != nil {\n        panic(err)\n    }\n    fmt.Println(\"user info:\", userMap)\n}\n\n```\n\n##### 3. 列表（List）\n列表是一个有序的字符串列表，支持在两端插入和删除元素。\n\n\n```GO\nfunc listOperations() {\n    \u002F\u002F 向列表左侧插入元素\n    err := rdb.LPush(ctx, \"tasks\", \"task1\", \"task2\", \"task3\").Err()\n    if err != nil {\n        panic(err)\n    }\n\n    \u002F\u002F 向列表右侧插入元素\n    err = rdb.RPush(ctx, \"tasks\", \"task4\").Err()\n    if err != nil {\n        panic(err)\n    }\n\n    \u002F\u002F 从左侧弹出元素\n    task, err := rdb.LPop(ctx, \"tasks\").Result()\n    if err != nil {\n        panic(err)\n    }\n    fmt.Println(\"popped task:\", task)\n\n    \u002F\u002F 获取列表长度\n    length, err := rdb.LLen(ctx, \"tasks\").Result()\n    if err != nil {\n        panic(err)\n    }\n    fmt.Println(\"tasks count:\", length)\n\n    \u002F\u002F 获取列表中的所有元素\n    tasks, err := rdb.LRange(ctx, \"tasks\", 0, -1).Result()\n    if err != nil {\n        panic(err)\n    }\n    fmt.Println(\"remaining tasks:\", tasks)\n}\n\n```\n\n##### 4. 集合（Set）\n集合是无序的字符串集合，支持交集、并集、差集等操作。\n\n\n```GO\nfunc setOperations() {\n    \u002F\u002F 向集合添加元素\n    err := rdb.SAdd(ctx, \"tags:post:1\", \"go\", \"redis\", \"database\").Err()\n    if err != nil {\n        panic(err)\n    }\n\n    err = rdb.SAdd(ctx, \"tags:post:2\", \"go\", \"web\", \"api\").Err()\n    if err != nil {\n        panic(err)\n    }\n\n    \u002F\u002F 检查元素是否在集合中\n    isMember, err := rdb.SIsMember(ctx, \"tags:post:1\", \"redis\").Result()\n    if err != nil {\n        panic(err)\n    }\n    fmt.Println(\"is 'redis' in post1 tags:\", isMember)\n\n    \u002F\u002F 获取集合中的所有元素\n    tags, err := rdb.SMembers(ctx, \"tags:post:1\").Result()\n    if err != nil {\n        panic(err)\n    }\n    fmt.Println(\"post1 tags:\", tags)\n\n    \u002F\u002F 集合并集操作\n    union, err := rdb.SUnion(ctx, \"tags:post:1\", \"tags:post:2\").Result()\n    if err != nil {\n        panic(err)\n    }\n    fmt.Println(\"union of tags:\", union)\n\n    \u002F\u002F 集合交集操作\n    intersect, err := rdb.SInter(ctx, \"tags:post:1\", \"tags:post:2\").Result()\n    if err != nil {\n        panic(err)\n    }\n    fmt.Println(\"intersection of tags:\", intersect)\n}\n```\n\n##### 5. 有序集合（Sorted Set）\n有序集合与集合类似，但每个元素都关联一个分数，可以根据分数排序。\n\n\n```GO\nfunc sortedSetOperations() {\n    \u002F\u002F 向有序集合添加元素\n    err := rdb.ZAdd(ctx, \"leaderboard\", \n        &redis.Z{Score: 100, Member: \"player1\"},\n        &redis.Z{Score: 90, Member: \"player2\"},\n        &redis.Z{Score: 95, Member: \"player3\"}).Err()\n    if err != nil {\n        panic(err)\n    }\n\n    \u002F\u002F 增加成员分数\n    err = rdb.ZIncrBy(ctx, \"leaderboard\", 10, \"player2\").Err()\n    if err != nil {\n        panic(err)\n    }\n\n    \u002F\u002F 获取按分数排序的前N个成员\n    players, err := rdb.ZRevRangeWithScores(ctx, \"leaderboard\", 0, 2).Result()\n    if err != nil {\n        panic(err)\n    }\n    \n    fmt.Println(\"Leaderboard:\")\n    for i, player := range players {\n        fmt.Printf(\"%d. %v - %v points\\n\", i+1, player.Member, player.Score)\n    }\n}\n\n```\n\n### 实际应用场景代码示例\n##### 1. 缓存应用\n\n\n```GO\nfunc getCachedUser(userID string) (map[string]string, error) {\n    \u002F\u002F 首先尝试从缓存获取\n    cachedUser, err := rdb.HGetAll(ctx, \"user:\"+userID).Result()\n    if err != nil && err != redis.Nil {\n        return nil, err\n    }\n\n    \u002F\u002F 如果缓存中存在数据\n    if len(cachedUser) > 0 && cachedUser[\"name\"] != \"\" {\n        fmt.Println(\"从缓存获取用户信息\")\n        return cachedUser, nil\n    }\n\n    \u002F\u002F 模拟从数据库获取数据\n    fmt.Println(\"从数据库获取用户信息\")\n    user := map[string]string{\n        \"id\":    userID,\n        \"name\":  \"张三\",\n        \"email\": \"zhangsan@example.com\",\n    }\n\n    \u002F\u002F 将数据存入缓存，设置过期时间\n    err = rdb.HMSet(ctx, \"user:\"+userID, user).Err()\n    if err != nil {\n        return nil, err\n    }\n    \n    \u002F\u002F 设置过期时间\n    rdb.Expire(ctx, \"user:\"+userID, 10*time.Minute)\n\n    return user, nil\n}\n\n```\n##### 2. 分布式锁\n\n```GO\nfunc acquireLock(lockKey string, timeout time.Duration) (string, error) {\n    \u002F\u002F 生成唯一标识\n    lockValue := fmt.Sprintf(\"%d\", time.Now().UnixNano())\n    \n    \u002F\u002F 尝试获取锁，设置过期时间防止死锁\n    ok, err := rdb.SetNX(ctx, lockKey, lockValue, timeout).Result()\n    if err != nil {\n        return \"\", err\n    }\n    \n    if !ok {\n        return \"\", fmt.Errorf(\"无法获取锁\")\n    }\n    \n    return lockValue, nil\n}\n\nfunc releaseLock(lockKey, lockValue string) error {\n    \u002F\u002F 使用Lua脚本确保原子性\n    script := `\n        if redis.call(\"GET\", KEYS[1]) == ARGV[1] then\n            return redis.call(\"DEL\", KEYS[1])\n        else\n            return 0\n        end\n    `\n    \n    result, err := rdb.Eval(ctx, script, []string{lockKey}, lockValue).Result()\n    if err != nil {\n        return err\n    }\n    \n    if result.(int64) == 0 {\n        return fmt.Errorf(\"锁已失效或被其他进程持有\")\n    }\n    \n    return nil\n}\n\nfunc doWithLock(lockKey string, fn func() error) error {\n    lockValue, err := acquireLock(lockKey, 10*time.Second)\n    if err != nil {\n        return err\n    }\n    defer releaseLock(lockKey, lockValue)\n    \n    return fn()\n}\n```\n\n##### 3. 消息队列\n\n```GO\n\u002F\u002F 生产者\nfunc produceMessage(queueName, message string) error {\n    return rdb.LPush(ctx, queueName, message).Err()\n}\n\n\u002F\u002F 消费者\nfunc consumeMessage(queueName string) (string, error) {\n    \u002F\u002F 阻塞式弹出消息，超时时间为1秒\n    result, err := rdb.BRPop(ctx, 1*time.Second, queueName).Result()\n    if err != nil {\n        return \"\", err\n    }\n    \n    \u002F\u002F BRPop返回的是包含键名和值的数组，我们只需要值\n    if len(result) >= 2 {\n        return result[1], nil\n    }\n    \n    return \"\", fmt.Errorf(\"无法获取消息\")\n}\n\nfunc messageQueueExample() {\n    queueName := \"task_queue\"\n    \n    \u002F\u002F 启动生产者\n    go func() {\n        for i := 0; i \u003C 5; i++ {\n            message := fmt.Sprintf(\"task_%d\", i)\n            err := produceMessage(queueName, message)\n            if err != nil {\n                fmt.Printf(\"生产消息失败: %v\\n\", err)\n            } else {\n                fmt.Printf(\"生产消息: %s\\n\", message)\n            }\n            time.Sleep(1 * time.Second)\n        }\n    }()\n    \n    \u002F\u002F 启动消费者\n    go func() {\n        for {\n            message, err := consumeMessage(queueName)\n            if err != nil {\n                if err != redis.Nil {\n                    fmt.Printf(\"消费消息失败: %v\\n\", err)\n                }\n                time.Sleep(1 * time.Second)\n                continue\n            }\n            \n            fmt.Printf(\"消费消息: %s\\n\", message)\n            \u002F\u002F 模拟处理时间\n            time.Sleep(2 * time.Second)\n        }\n    }()\n}\n\n```\n\n### 完整示例\n\n```GO\nfunc main() {\n    \u002F\u002F 测试连接\n    pong, err := rdb.Ping(ctx).Result()\n    if err != nil {\n        fmt.Println(\"连接Redis失败:\", err)\n        return\n    }\n    fmt.Println(\"连接成功:\", pong)\n\n    \u002F\u002F 执行各种操作\n    fmt.Println(\"=== 字符串操作 ===\")\n    stringOperations()\n\n    fmt.Println(\"\\n=== 哈希操作 ===\")\n    hashOperations()\n\n    fmt.Println(\"\\n=== 列表操作 ===\")\n    listOperations()\n\n    fmt.Println(\"\\n=== 集合操作 ===\")\n    setOperations()\n\n    fmt.Println(\"\\n=== 有序集合操作 ===\")\n    sortedSetOperations()\n\n    fmt.Println(\"\\n=== 缓存示例 ===\")\n    user, err := getCachedUser(\"123\")\n    if err != nil {\n        fmt.Printf(\"获取用户失败: %v\\n\", err)\n    } else {\n        fmt.Printf(\"获取用户: %+v\\n\", user)\n    }\n\n    \u002F\u002F 再次获取同一用户，应该从缓存获取\n    user, err = getCachedUser(\"123\")\n    if err != nil {\n        fmt.Printf(\"获取用户失败: %v\\n\", err)\n    } else {\n        fmt.Printf(\"获取用户: %+v\\n\", user)\n    }\n\n    fmt.Println(\"\\n=== 分布式锁示例 ===\")\n    err = doWithLock(\"test_lock\", func() error {\n        fmt.Println(\"执行需要锁保护的操作\")\n        time.Sleep(3 * time.Second)\n        return nil\n    })\n    if err != nil {\n        fmt.Printf(\"执行锁保护操作失败: %v\\n\", err)\n    }\n\n    fmt.Println(\"\\n=== 消息队列示例 ===\")\n    messageQueueExample()\n    \n    \u002F\u002F 等待一段时间以便观察消息队列示例的输出\n    time.Sleep(10 * time.Second)\n}\n```\n","### Redis Practical Guide: From Basic Concepts to Go Language Applications\n\n> Redis (Remote Dictionary Server) is an open-source in-memory data structure storage system that can not only be used as a database, cache, and message broker, but also supports a variety of data structures, such as strings, hashes, lists, collections, and ordered collections. Today we will take an in-depth look at the use of Redis with actual Go code examples.\n\n#### Redis Basic Data Structure and Operation\n\n##### 1. 字符串（String）\n\nStrings are the most basic data type in Redis and can store text, number, or binary data.\n\n```GO\npackage main\n\nimport (\n    \"context\"\n    \"fmt\"\n    \"time\"\n    \"github.com\u002Fgo-redis\u002Fredis\u002Fv8\"\n)\n\nvar ctx = context. Background()\nvar rdb *redis. Client\n\nfunc init() {\n    rdb = redis. NewClient(&redis. Options{\n        Addr:     \"localhost:6379\",\n        Password: \"\", \u002F\u002F no password set\n        DB:       0,  \u002F\u002F use default DB\n    })\n}\n\nfunc stringOperations() {\n    Set the key-value pair\n    err := rdb. Set(ctx, \"name\", \"Redis\", 0). Err()\n    if err != nil {\n        panic(err)\n    }\n\n    Get the key value\n    val, err := rdb. Get(ctx, \"name\"). Result()\n    if err != nil {\n        panic(err)\n    }\n    FMT. Printlon(\"In name:\", good)\n\n    Set key-value pairs with expiration times\n    err = rdb. Set(ctx, \"counter\", 0, 1*time. Hour). Err()\n    if err != nil {\n        panic(err)\n    }\n\n    Self-increment operation\n    err = rdb. Incr(ctx, \"counter\"). Err()\n    if err != nil {\n        panic(err)\n    }\n\n    val, err = rdb. Get(ctx, \"counter\"). Result()\n    if err != nil {\n        panic(err)\n    }\n    fmt. Println(\"counter:\", val)\n}\n\n```\n##### 2nd 哈希(hash)\n\nHashing allows us to store multiple key-value pairs under a single key, making it ideal for storing objects.\n\n\n```GO\nfunc hashOperations() {\n    Set the hash field\n    err := rdb. HSet(ctx, \"user:1000\", \"name\", \"张三\"). Err()\n    if err != nil {\n        panic(err)\n    }\n    \n    err = rdb. HSet(ctx, \"user:1000\", \"email\", \"zhangsan@example.com\"). Err()\n    if err != nil {\n        panic(err)\n    }\n\n    Get a single field\n    name, err := rdb. HGet(ctx, \"user:1000\", \"name\"). Result()\n    if err != nil {\n        panic(err)\n    }\n    fmt. Println(\"user name:\", name)\n\n    Get all the fields\n    userMap, err := rdb. HGetAll(ctx, \"user:1000\"). Result()\n    if err != nil {\n        panic(err)\n    }\n    fmt. Println(\"user info:\", userMap)\n}\n\n```\n\n##### 3. List\nA list is an ordered list of strings that supports inserting and removing elements at both ends.\n\n\n```GO\nfunc listOperations() {\n    Insert elements to the left of the list\n    err := rdb. LPush(ctx, \"tasks\", \"task1\", \"task2\", \"task3\"). Err()\n    if err != nil {\n        panic(err)\n    }\n\n    Insert elements to the right of the list\n    err = rdb. RPush(ctx, \"tasks\", \"task4\"). Err()\n    if err != nil {\n        panic(err)\n    }\n\n    Pop up the element from the left\n    task, err := rdb. LPop(ctx, \"tasks\"). Result()\n    if err != nil {\n        panic(err)\n    }\n    fmt. Println(\"popped task:\", task)\n\n    Get the list length\n    length, err := rdb. LLen(ctx, \"tasks\"). Result()\n    if err != nil {\n        panic(err)\n    }\n    fmt. Println(\"tasks count:\", length)\n\n    Get all the elements in the list\n    tasks, err := rdb. LRange(ctx, \"tasks\", 0, -1). Result()\n    if err != nil {\n        panic(err)\n    }\n    fmt. Println(\"remaining tasks:\", tasks)\n}\n\n```\n\n##### 4. Set\nA collection is an unordered collection of strings that supports operations such as intersection, union, and difference set.\n\n\n```GO\nfunc setOperations() {\n    Add elements to the collection\n    err := rdb. SAdd(ctx, \"tags:post:1\", \"go\", \"redis\", \"database\"). Err()\n    if err != nil {\n        panic(err)\n    }\n\n    err = rdb. SAdd(ctx, \"tags:post:2\", \"go\", \"web\", \"api\"). Err()\n    if err != nil {\n        panic(err)\n    }\n\n    Check if the element is in the collection\n    isMember, err := rdb. SIsMember(ctx, \"tags:post:1\", \"redis\"). Result()\n    if err != nil {\n        panic(err)\n    }\n    fmt. Println(\"is 'redis' in post1 tags:\", isMember)\n\n    Get all the elements in the collection\n    tags, err := rdb. SMembers(ctx, \"tags:post:1\"). Result()\n    if err != nil {\n        panic(err)\n    }\n    fmt. Println(\"post1 tags:\", tags)\n\n    Collect union operations\n    union, err := rdb. SUnion(ctx, \"tags:post:1\", \"tags:post:2\"). Result()\n    if err != nil {\n        panic(err)\n    }\n    fmt. Println(\"union of tags:\", union)\n\n    Collection intersection operations\n    intersect, err := rdb. SInter(ctx, \"tags:post:1\", \"tags:post:2\"). Result()\n    if err != nil {\n        panic(err)\n    }\n    fmt. Println(\"intersection of tags:\", intersect)\n}\n```\n\n##### 5. 有序集合（Sorted Set）\nOrdered sets are similar to collections, but each element has a score associated with it, which can be sorted based on the score.\n\n\n```GO\nfunc sortedSetOperations() {\n    Add elements to an ordered collection\n    err := rdb. ZAdd(ctx, \"leaderboard\", \n        &redis. Z{Score: 100, Member: \"player1\"},\n        &redis. Z{Score: 90, Member: \"player2\"},\n        &redis. Z{Score: 95, Member: \"player3\"}). Err()\n    if err != nil {\n        panic(err)\n    }\n\n    Increase member scores\n    err = rdb. ZIncrBy(ctx, \"leaderboard\", 10, \"player2\"). Err()\n    if err != nil {\n        panic(err)\n    }\n\n    Get the top N members sorted by score\n    players, err := rdb. ZRevRangeWithScores(ctx, \"leaderboard\", 0, 2). Result()\n    if err != nil {\n        panic(err)\n    }\n    \n    fmt. Println(\"Leaderboard:\")\n    for i, player := range players {\n        fmt. Printf(\"%d. %v - %v points\\n\", i+1, player. Member, player. Score)\n    }\n}\n\n```\n\n### Code examples for practical application scenarios\n##### 1. Caching applications\n\n\n```GO\nfunc getCachedUser(userID string) (map[string]string, error) {\n    Try getting it from the cache first\n    cachedUser, err := rdb. HGetAll(ctx, \"user:\"+userID). Result()\n    if err != nil && err != redis. Nil {\n        return nil, err\n    }\n\n    If data exists in the cache\n    if len(cachedUser) > 0 && cachedUser[\"name\"] != \"\" {\n        fmt. Println (\"Get user information from cache\")\n        return cachedUser, nil\n    }\n\n    Simulate getting data from a database\n    fmt. Println (\"Get User Information from Database\")\n    user := map[string]string{\n        \"id\":    userID,\n        \"name\": \"Zhang San\",\n        \"email\": \"zhangsan@example.com\",\n    }\n\n    Deposit data into the cache and set an expiration time\n    err = rdb. HMSet(ctx, \"user:\"+userID, user). Err()\n    if err != nil {\n        return nil, err\n    }\n    \n    Set the expiration time\n    rdb. Expire(ctx, \"user:\"+userID, 10*time. Minute)\n\n    return user, nil\n}\n\n```\n##### 2. Distributed locks\n\n```GO\nfunc acquireLock(lockKey string, timeout time. Duration) (string, error) {\n    Generate a unique identity\n    lockValue := fmt. Sprintf(\"%d\", time. Now(). UnixNano())\n    \n    Try to get a lock, set an expiration time to prevent deadlocks\n    ok, err := rdb. SetNX(ctx, lockKey, lockValue, timeout). Result()\n    if err != nil {\n        return \"\", err\n    }\n    \n    if !ok {\n        return \"\", fmt. Errorf(\"无法获取锁\")\n    }\n    \n    return lockValue, nil\n}\n\nfunc releaseLock(lockKey, lockValue string) error {\n    Use Lua scripts to ensure atomicity\n    script := `\n        if redis.call(\"GET\", KEYS[1]) == ARGV[1] then\n            return redis.call(\"DEL\", KEYS[1])\n        else\n            return 0\n        end\n    `\n    \n    result, err := rdb. Eval(ctx, script, []string{lockKey}, lockValue). Result()\n    if err != nil {\n        return err\n    }\n    \n    if result. (int64) == 0 {\n        return fmt. Errorf(\"Lock has expired or is held by another process\")\n    }\n    \n    return nil\n}\n\nfunc doWithLock(lockKey string, fn func() error) error {\n    lockValue, err := acquireLock(lockKey, 10*time. Second)\n    if err != nil {\n        return err\n    }\n    defer releaseLock(lockKey, lockValue)\n    \n    return fn()\n}\n```\n\n##### 3. Message queue\n\n```GO\nproducer\nfunc produceMessage(queueName, message string) error {\n    return rdb. LPush(ctx, queueName, message). Err()\n}\n\nconsumer\nfunc consumeMessage(queueName string) (string, error) {\n    Blocking pop-up message with a timeout of 1 second\n    result, err := rdb. BRPop(ctx, 1*time. Second, queueName). Result()\n    if err != nil {\n        return \"\", err\n    }\n    \n    BRPop returns an array with key names and values, we only need values\n    if len(result) >= 2 {\n        return result[1], nil\n    }\n    \n    return \"\", fmt. Errorf(\"Unable to get message\")\n}\n\nfunc messageQueueExample() {\n    queueName := \"task_queue\"\n    \n    Startup producers\n    go func() {\n        for i := 0; i \u003C 5; i++ {\n            Message:= fmt. Sprintf(\"task_%d\", i)\n            err := produceMessage(queueName, message)\n            if err != nil {\n                fmt. Printf(\"生产消息失败: %v\\n\", err)\n            } else {\n                fmt. Printf(\"生产消息: %s\\n\", message)\n            }\n            time. Sleep(1 * time. Second)\n        }\n    }()\n    \n    Activate the consumer\n    go func() {\n        for {\n            message, err := consumeMessage(queueName)\n            if err != nil {\n                if err != redis. Nil {\n                    fmt. Printf(\"消费消息失败: %v\\n\", err)\n                }\n                time. Sleep(1 * time. Second)\n                Go on\n            }\n            \n            fmt. Printf(\"消费消息: %s\\n\", message)\n            Simulate processing time\n            time. Sleep(2 * time. Second)\n        }\n    }()\n}\n\n```\n\n### Full example\n\n```GO\nfunc main() {\n    Test the connection\n    pong, err := rdb. Ping(ctx). Result()\n    if err != nil {\n        fmt. Println(\"连接 Redis 失败:\", err)\n        return\n    }\n    fmt. Println(\"连接成功:\", pong)\n\n    Perform various actions\n    Fmt. Println(\"=== 字符串操作 ===\")\n    stringOperations()\n\n    fmt. Println(\"\\n=== 哈希操作 ===\")\n    hashOperations()\n\n    fmt. Println(\"\\n=== List Operation ===\")\n    listOperations()\n\n    fmt. Println(\"\\n=== Collection Operation ===\")\n    setOperations()\n\n    fmt. println(\"\\n=== Ordered Collection Operation ===\")\n    sortedSetOperations()\n\n    fmt. Println(\"\\n=== 缓存示例 ===\")\n    user, err := getCachedUser(\"123\")\n    if err != nil {\n        fmt. Printf(\"获取用户失败: %v\\n\", err)\n    } else {\n        fmt. Printf(\"获取用户: %+v\\n\", user)\n    }\n\n    To get the same user again, it should be from the cache\n    user, err = getCachedUser(\"123\")\n    if err != nil {\n        fmt. Printf(\"获取用户失败: %v\\n\", err)\n    } else {\n        fmt. Printf(\"获取用户: %+v\\n\", user)\n    }\n\n    fmt. println(\"\\n=== Distributed Lock Example ===\")\n    err = doWithLock(\"test_lock\", func() error {\n        fmt. Println(\"Perform an operation that requires lock protection\")\n        time. Sleep(3 * time. Second)\n        return nil\n    })\n    if err != nil {\n        fmt. Printf(\"Failed to execute lock protection operation: %v\\n\", err)\n    }\n\n    fmt. Println(\"\\n=== Message Queue Example ===\")\n    messageQueueExample()\n    \n    Wait a while to observe the output of the message queue sample\n    time. Sleep(10 * time. Second)\n}\n```\n","Redis",0,"https:\u002F\u002Fblog4-1316398321.cos.ap-nanjing.myqcloud.com\u002Fblog5\u002F20250814151835__无人机照片.png",[13,9],"GO",false,{"id":16,"title":17,"title_en":18},19,"Vue3中基于mitt的类型安全事件总线实现","Implementation of type-safe event bus based on mitt in Vue3",{"id":20,"title":21,"title_en":22},21,"Vue 3 + Vite 项目中实现 i18n","Implementation of i18n in Vue 3 + Vite project","2025-08-14T23:06:50+08:00"]