676 lines
18 KiB
Go
676 lines
18 KiB
Go
package main
|
||
|
||
import (
|
||
"context"
|
||
"encoding/json"
|
||
"fmt"
|
||
"log"
|
||
"time"
|
||
|
||
"github.com/redis/go-redis/v9"
|
||
)
|
||
|
||
// RedisClient Redis客户端结构体
|
||
type RedisClient struct {
|
||
Client *redis.Client
|
||
Ctx context.Context
|
||
}
|
||
|
||
// RedisConfig Redis配置结构体
|
||
type RedisConfig struct {
|
||
Addr string // 服务器地址:端口
|
||
Password string // 密码
|
||
DB int // 数据库编号
|
||
PoolSize int // 连接池大小
|
||
MinIdleConns int // 最小空闲连接数
|
||
DialTimeout time.Duration // 连接超时
|
||
ReadTimeout time.Duration // 读取超时
|
||
WriteTimeout time.Duration // 写入超时
|
||
PoolTimeout time.Duration // 获取连接超时
|
||
}
|
||
|
||
// NewRedisClient 创建新的Redis客户端
|
||
func NewRedisClient(config *RedisConfig) *RedisClient {
|
||
if config == nil {
|
||
// 默认配置 - 根据您的需求设置
|
||
config = &RedisConfig{
|
||
Addr: "36.212.20.113:7963",
|
||
Password: "",
|
||
DB: 2,
|
||
PoolSize: 10,
|
||
MinIdleConns: 5,
|
||
DialTimeout: 5 * time.Second,
|
||
ReadTimeout: 3 * time.Second,
|
||
WriteTimeout: 3 * time.Second,
|
||
PoolTimeout: 4 * time.Second,
|
||
}
|
||
}
|
||
|
||
rdb := redis.NewClient(&redis.Options{
|
||
Addr: config.Addr,
|
||
Password: config.Password,
|
||
DB: config.DB,
|
||
PoolSize: config.PoolSize,
|
||
MinIdleConns: config.MinIdleConns,
|
||
DialTimeout: config.DialTimeout,
|
||
ReadTimeout: config.ReadTimeout,
|
||
WriteTimeout: config.WriteTimeout,
|
||
PoolTimeout: config.PoolTimeout,
|
||
})
|
||
|
||
return &RedisClient{
|
||
Client: rdb,
|
||
Ctx: context.Background(),
|
||
}
|
||
}
|
||
|
||
// Close 关闭Redis连接
|
||
func (r *RedisClient) Close() error {
|
||
return r.Client.Close()
|
||
}
|
||
|
||
// Ping 测试连接
|
||
func (r *RedisClient) Ping() error {
|
||
pong, err := r.Client.Ping(r.Ctx).Result()
|
||
if err != nil {
|
||
return fmt.Errorf("Redis连接失败: %v", err)
|
||
}
|
||
log.Printf("Redis连接成功: %s", pong)
|
||
return nil
|
||
}
|
||
|
||
// ==================== 字符串操作 ====================
|
||
|
||
// Set 设置键值对
|
||
func (r *RedisClient) Set(key string, value interface{}, expiration time.Duration) error {
|
||
err := r.Client.Set(r.Ctx, key, value, expiration).Err()
|
||
if err != nil {
|
||
return fmt.Errorf("设置键 %s 失败: %v", key, err)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// Get 获取字符串值
|
||
func (r *RedisClient) Get(key string) (string, error) {
|
||
val, err := r.Client.Get(r.Ctx, key).Result()
|
||
if err == redis.Nil {
|
||
return "", fmt.Errorf("键 %s 不存在", key)
|
||
} else if err != nil {
|
||
return "", fmt.Errorf("获取键 %s 失败: %v", key, err)
|
||
}
|
||
return val, nil
|
||
}
|
||
|
||
// GetInt 获取整数值
|
||
func (r *RedisClient) GetInt(key string) (int, error) {
|
||
val, err := r.Client.Get(r.Ctx, key).Int()
|
||
if err == redis.Nil {
|
||
return 0, fmt.Errorf("键 %s 不存在", key)
|
||
} else if err != nil {
|
||
return 0, fmt.Errorf("获取键 %s 失败: %v", key, err)
|
||
}
|
||
return val, nil
|
||
}
|
||
|
||
// GetInt64 获取64位整数值
|
||
func (r *RedisClient) GetInt64(key string) (int64, error) {
|
||
val, err := r.Client.Get(r.Ctx, key).Int64()
|
||
if err == redis.Nil {
|
||
return 0, fmt.Errorf("键 %s 不存在", key)
|
||
} else if err != nil {
|
||
return 0, fmt.Errorf("获取键 %s 失败: %v", key, err)
|
||
}
|
||
return val, nil
|
||
}
|
||
|
||
// GetFloat64 获取浮点数值
|
||
func (r *RedisClient) GetFloat64(key string) (float64, error) {
|
||
val, err := r.Client.Get(r.Ctx, key).Float64()
|
||
if err == redis.Nil {
|
||
return 0, fmt.Errorf("键 %s 不存在", key)
|
||
} else if err != nil {
|
||
return 0, fmt.Errorf("获取键 %s 失败: %v", key, err)
|
||
}
|
||
return val, nil
|
||
}
|
||
|
||
// GetBool 获取布尔值
|
||
func (r *RedisClient) GetBool(key string) (bool, error) {
|
||
val, err := r.Client.Get(r.Ctx, key).Bool()
|
||
if err == redis.Nil {
|
||
return false, fmt.Errorf("键 %s 不存在", key)
|
||
} else if err != nil {
|
||
return false, fmt.Errorf("获取键 %s 失败: %v", key, err)
|
||
}
|
||
return val, nil
|
||
}
|
||
|
||
// SetNX 只有当键不存在时设置值
|
||
func (r *RedisClient) SetNX(key string, value interface{}, expiration time.Duration) (bool, error) {
|
||
success, err := r.Client.SetNX(r.Ctx, key, value, expiration).Result()
|
||
if err != nil {
|
||
return false, fmt.Errorf("SetNX操作失败: %v", err)
|
||
}
|
||
return success, nil
|
||
}
|
||
|
||
// SetXX 只有当键存在时设置值
|
||
func (r *RedisClient) SetXX(key string, value interface{}, expiration time.Duration) (bool, error) {
|
||
success, err := r.Client.SetXX(r.Ctx, key, value, expiration).Result()
|
||
if err != nil {
|
||
return false, fmt.Errorf("SetXX操作失败: %v", err)
|
||
}
|
||
return success, nil
|
||
}
|
||
|
||
// MSet 批量设置键值对
|
||
func (r *RedisClient) MSet(values map[string]interface{}) error {
|
||
pairs := make([]interface{}, 0, len(values)*2)
|
||
for k, v := range values {
|
||
pairs = append(pairs, k, v)
|
||
}
|
||
err := r.Client.MSet(r.Ctx, pairs...).Err()
|
||
if err != nil {
|
||
return fmt.Errorf("批量设置失败: %v", err)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// MGet 批量获取值
|
||
func (r *RedisClient) MGet(keys ...string) ([]interface{}, error) {
|
||
vals, err := r.Client.MGet(r.Ctx, keys...).Result()
|
||
if err != nil {
|
||
return nil, fmt.Errorf("批量获取失败: %v", err)
|
||
}
|
||
return vals, nil
|
||
}
|
||
|
||
// Incr 自增1
|
||
func (r *RedisClient) Incr(key string) (int64, error) {
|
||
val, err := r.Client.Incr(r.Ctx, key).Result()
|
||
if err != nil {
|
||
return 0, fmt.Errorf("自增失败: %v", err)
|
||
}
|
||
return val, nil
|
||
}
|
||
|
||
// IncrBy 自增指定值
|
||
func (r *RedisClient) IncrBy(key string, value int64) (int64, error) {
|
||
val, err := r.Client.IncrBy(r.Ctx, key, value).Result()
|
||
if err != nil {
|
||
return 0, fmt.Errorf("自增 %d 失败: %v", value, err)
|
||
}
|
||
return val, nil
|
||
}
|
||
|
||
// Decr 自减1
|
||
func (r *RedisClient) Decr(key string) (int64, error) {
|
||
val, err := r.Client.Decr(r.Ctx, key).Result()
|
||
if err != nil {
|
||
return 0, fmt.Errorf("自减失败: %v", err)
|
||
}
|
||
return val, nil
|
||
}
|
||
|
||
// DecrBy 自减指定值
|
||
func (r *RedisClient) DecrBy(key string, value int64) (int64, error) {
|
||
val, err := r.Client.DecrBy(r.Ctx, key, value).Result()
|
||
if err != nil {
|
||
return 0, fmt.Errorf("自减 %d 失败: %v", value, err)
|
||
}
|
||
return val, nil
|
||
}
|
||
|
||
// Append 追加字符串
|
||
func (r *RedisClient) Append(key, value string) (int64, error) {
|
||
length, err := r.Client.Append(r.Ctx, key, value).Result()
|
||
if err != nil {
|
||
return 0, fmt.Errorf("追加字符串失败: %v", err)
|
||
}
|
||
return length, nil
|
||
}
|
||
|
||
// StrLen 获取字符串长度
|
||
func (r *RedisClient) StrLen(key string) (int64, error) {
|
||
length, err := r.Client.StrLen(r.Ctx, key).Result()
|
||
if err != nil {
|
||
return 0, fmt.Errorf("获取字符串长度失败: %v", err)
|
||
}
|
||
return length, nil
|
||
}
|
||
|
||
// ==================== 键操作 ====================
|
||
|
||
// Exists 检查键是否存在
|
||
func (r *RedisClient) Exists(keys ...string) (int64, error) {
|
||
count, err := r.Client.Exists(r.Ctx, keys...).Result()
|
||
if err != nil {
|
||
return 0, fmt.Errorf("检查键是否存在失败: %v", err)
|
||
}
|
||
return count, nil
|
||
}
|
||
|
||
// Del 删除键
|
||
func (r *RedisClient) Del(keys ...string) (int64, error) {
|
||
count, err := r.Client.Del(r.Ctx, keys...).Result()
|
||
if err != nil {
|
||
return 0, fmt.Errorf("删除键失败: %v", err)
|
||
}
|
||
return count, nil
|
||
}
|
||
|
||
// Expire 设置过期时间
|
||
func (r *RedisClient) Expire(key string, expiration time.Duration) (bool, error) {
|
||
success, err := r.Client.Expire(r.Ctx, key, expiration).Result()
|
||
if err != nil {
|
||
return false, fmt.Errorf("设置过期时间失败: %v", err)
|
||
}
|
||
return success, nil
|
||
}
|
||
|
||
// TTL 获取剩余过期时间
|
||
func (r *RedisClient) TTL(key string) (time.Duration, error) {
|
||
ttl, err := r.Client.TTL(r.Ctx, key).Result()
|
||
if err != nil {
|
||
return 0, fmt.Errorf("获取过期时间失败: %v", err)
|
||
}
|
||
return ttl, nil
|
||
}
|
||
|
||
// Persist 移除过期时间
|
||
func (r *RedisClient) Persist(key string) (bool, error) {
|
||
success, err := r.Client.Persist(r.Ctx, key).Result()
|
||
if err != nil {
|
||
return false, fmt.Errorf("移除过期时间失败: %v", err)
|
||
}
|
||
return success, nil
|
||
}
|
||
|
||
// Type 获取键类型
|
||
func (r *RedisClient) Type(key string) (string, error) {
|
||
typeStr, err := r.Client.Type(r.Ctx, key).Result()
|
||
if err != nil {
|
||
return "", fmt.Errorf("获取键类型失败: %v", err)
|
||
}
|
||
return typeStr, nil
|
||
}
|
||
|
||
// Keys 查找所有匹配的键
|
||
func (r *RedisClient) Keys(pattern string) ([]string, error) {
|
||
keys, err := r.Client.Keys(r.Ctx, pattern).Result()
|
||
if err != nil {
|
||
return nil, fmt.Errorf("查找键失败: %v", err)
|
||
}
|
||
return keys, nil
|
||
}
|
||
|
||
// RandomKey 随机获取一个键
|
||
func (r *RedisClient) RandomKey() (string, error) {
|
||
key, err := r.Client.RandomKey(r.Ctx).Result()
|
||
if err != nil {
|
||
return "", fmt.Errorf("随机获取键失败: %v", err)
|
||
}
|
||
return key, nil
|
||
}
|
||
|
||
// Rename 重命名键
|
||
func (r *RedisClient) Rename(key, newKey string) error {
|
||
err := r.Client.Rename(r.Ctx, key, newKey).Err()
|
||
if err != nil {
|
||
return fmt.Errorf("重命名键失败: %v", err)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// RenameNX 只有当新键不存在时重命名
|
||
func (r *RedisClient) RenameNX(key, newKey string) (bool, error) {
|
||
success, err := r.Client.RenameNX(r.Ctx, key, newKey).Result()
|
||
if err != nil {
|
||
return false, fmt.Errorf("重命名键失败: %v", err)
|
||
}
|
||
return success, nil
|
||
}
|
||
|
||
// ==================== Hash操作 ====================
|
||
|
||
// HSet 设置Hash字段
|
||
func (r *RedisClient) HSet(key string, values ...interface{}) error {
|
||
err := r.Client.HSet(r.Ctx, key, values...).Err()
|
||
if err != nil {
|
||
return fmt.Errorf("设置Hash失败: %v", err)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// HGet 获取Hash字段
|
||
func (r *RedisClient) HGet(key, field string) (string, error) {
|
||
val, err := r.Client.HGet(r.Ctx, key, field).Result()
|
||
if err == redis.Nil {
|
||
return "", fmt.Errorf("字段 %s 不存在", field)
|
||
} else if err != nil {
|
||
return "", fmt.Errorf("获取Hash字段失败: %v", err)
|
||
}
|
||
return val, nil
|
||
}
|
||
|
||
// HGetAll 获取所有Hash字段
|
||
func (r *RedisClient) HGetAll(key string) (map[string]string, error) {
|
||
vals, err := r.Client.HGetAll(r.Ctx, key).Result()
|
||
if err != nil {
|
||
return nil, fmt.Errorf("获取所有Hash字段失败: %v", err)
|
||
}
|
||
return vals, nil
|
||
}
|
||
|
||
// HDel 删除Hash字段
|
||
func (r *RedisClient) HDel(key string, fields ...string) (int64, error) {
|
||
count, err := r.Client.HDel(r.Ctx, key, fields...).Result()
|
||
if err != nil {
|
||
return 0, fmt.Errorf("删除Hash字段失败: %v", err)
|
||
}
|
||
return count, nil
|
||
}
|
||
|
||
// HExists 检查Hash字段是否存在
|
||
func (r *RedisClient) HExists(key, field string) (bool, error) {
|
||
exists, err := r.Client.HExists(r.Ctx, key, field).Result()
|
||
if err != nil {
|
||
return false, fmt.Errorf("检查Hash字段失败: %v", err)
|
||
}
|
||
return exists, nil
|
||
}
|
||
|
||
// HKeys 获取所有Hash字段名
|
||
func (r *RedisClient) HKeys(key string) ([]string, error) {
|
||
keys, err := r.Client.HKeys(r.Ctx, key).Result()
|
||
if err != nil {
|
||
return nil, fmt.Errorf("获取Hash字段名失败: %v", err)
|
||
}
|
||
return keys, nil
|
||
}
|
||
|
||
// HVals 获取所有Hash字段值
|
||
func (r *RedisClient) HVals(key string) ([]string, error) {
|
||
vals, err := r.Client.HVals(r.Ctx, key).Result()
|
||
if err != nil {
|
||
return nil, fmt.Errorf("获取Hash字段值失败: %v", err)
|
||
}
|
||
return vals, nil
|
||
}
|
||
|
||
// HLen 获取Hash字段数量
|
||
func (r *RedisClient) HLen(key string) (int64, error) {
|
||
count, err := r.Client.HLen(r.Ctx, key).Result()
|
||
if err != nil {
|
||
return 0, fmt.Errorf("获取Hash字段数量失败: %v", err)
|
||
}
|
||
return count, nil
|
||
}
|
||
|
||
// HIncrBy Hash字段自增
|
||
func (r *RedisClient) HIncrBy(key, field string, incr int64) (int64, error) {
|
||
val, err := r.Client.HIncrBy(r.Ctx, key, field, incr).Result()
|
||
if err != nil {
|
||
return 0, fmt.Errorf("Hash字段自增失败: %v", err)
|
||
}
|
||
return val, nil
|
||
}
|
||
|
||
// ==================== List操作 ====================
|
||
|
||
// LPush 从左侧插入列表
|
||
func (r *RedisClient) LPush(key string, values ...interface{}) (int64, error) {
|
||
count, err := r.Client.LPush(r.Ctx, key, values...).Result()
|
||
if err != nil {
|
||
return 0, fmt.Errorf("LPush失败: %v", err)
|
||
}
|
||
return count, nil
|
||
}
|
||
|
||
// RPush 从右侧插入列表
|
||
func (r *RedisClient) RPush(key string, values ...interface{}) (int64, error) {
|
||
count, err := r.Client.RPush(r.Ctx, key, values...).Result()
|
||
if err != nil {
|
||
return 0, fmt.Errorf("RPush失败: %v", err)
|
||
}
|
||
return count, nil
|
||
}
|
||
|
||
// LPop 从左侧弹出元素
|
||
func (r *RedisClient) LPop(key string) (string, error) {
|
||
val, err := r.Client.LPop(r.Ctx, key).Result()
|
||
if err == redis.Nil {
|
||
return "", fmt.Errorf("列表为空")
|
||
} else if err != nil {
|
||
return "", fmt.Errorf("LPop失败: %v", err)
|
||
}
|
||
return val, nil
|
||
}
|
||
|
||
// RPop 从右侧弹出元素
|
||
func (r *RedisClient) RPop(key string) (string, error) {
|
||
val, err := r.Client.RPop(r.Ctx, key).Result()
|
||
if err == redis.Nil {
|
||
return "", fmt.Errorf("列表为空")
|
||
} else if err != nil {
|
||
return "", fmt.Errorf("RPop失败: %v", err)
|
||
}
|
||
return val, nil
|
||
}
|
||
|
||
// LLen 获取列表长度
|
||
func (r *RedisClient) LLen(key string) (int64, error) {
|
||
length, err := r.Client.LLen(r.Ctx, key).Result()
|
||
if err != nil {
|
||
return 0, fmt.Errorf("获取列表长度失败: %v", err)
|
||
}
|
||
return length, nil
|
||
}
|
||
|
||
// LRange 获取列表范围
|
||
func (r *RedisClient) LRange(key string, start, stop int64) ([]string, error) {
|
||
vals, err := r.Client.LRange(r.Ctx, key, start, stop).Result()
|
||
if err != nil {
|
||
return nil, fmt.Errorf("获取列表范围失败: %v", err)
|
||
}
|
||
return vals, nil
|
||
}
|
||
|
||
// ==================== Set操作 ====================
|
||
|
||
// SAdd 添加集合元素
|
||
func (r *RedisClient) SAdd(key string, members ...interface{}) (int64, error) {
|
||
count, err := r.Client.SAdd(r.Ctx, key, members...).Result()
|
||
if err != nil {
|
||
return 0, fmt.Errorf("SAdd失败: %v", err)
|
||
}
|
||
return count, nil
|
||
}
|
||
|
||
// SMembers 获取所有集合成员
|
||
func (r *RedisClient) SMembers(key string) ([]string, error) {
|
||
members, err := r.Client.SMembers(r.Ctx, key).Result()
|
||
if err != nil {
|
||
return nil, fmt.Errorf("获取集合成员失败: %v", err)
|
||
}
|
||
return members, nil
|
||
}
|
||
|
||
// SIsMember 检查是否是集合成员
|
||
func (r *RedisClient) SIsMember(key string, member interface{}) (bool, error) {
|
||
exists, err := r.Client.SIsMember(r.Ctx, key, member).Result()
|
||
if err != nil {
|
||
return false, fmt.Errorf("检查集合成员失败: %v", err)
|
||
}
|
||
return exists, nil
|
||
}
|
||
|
||
// SCard 获取集合基数
|
||
func (r *RedisClient) SCard(key string) (int64, error) {
|
||
count, err := r.Client.SCard(r.Ctx, key).Result()
|
||
if err != nil {
|
||
return 0, fmt.Errorf("获取集合基数失败: %v", err)
|
||
}
|
||
return count, nil
|
||
}
|
||
|
||
// ==================== Sorted Set操作 ====================
|
||
|
||
// ZAdd 添加有序集合元素
|
||
func (r *RedisClient) ZAdd(key string, members ...redis.Z) (int64, error) {
|
||
count, err := r.Client.ZAdd(r.Ctx, key, members...).Result()
|
||
if err != nil {
|
||
return 0, fmt.Errorf("ZAdd失败: %v", err)
|
||
}
|
||
return count, nil
|
||
}
|
||
|
||
// ZRange 获取有序集合范围
|
||
func (r *RedisClient) ZRange(key string, start, stop int64) ([]string, error) {
|
||
vals, err := r.Client.ZRange(r.Ctx, key, start, stop).Result()
|
||
if err != nil {
|
||
return nil, fmt.Errorf("ZRange失败: %v", err)
|
||
}
|
||
return vals, nil
|
||
}
|
||
|
||
// ZRangeWithScores 获取有序集合范围和分数
|
||
func (r *RedisClient) ZRangeWithScores(key string, start, stop int64) ([]redis.Z, error) {
|
||
vals, err := r.Client.ZRangeWithScores(r.Ctx, key, start, stop).Result()
|
||
if err != nil {
|
||
return nil, fmt.Errorf("ZRangeWithScores失败: %v", err)
|
||
}
|
||
return vals, nil
|
||
}
|
||
|
||
// ZScore 获取元素分数
|
||
func (r *RedisClient) ZScore(key, member string) (float64, error) {
|
||
score, err := r.Client.ZScore(r.Ctx, key, member).Result()
|
||
if err == redis.Nil {
|
||
return 0, fmt.Errorf("元素不存在")
|
||
} else if err != nil {
|
||
return 0, fmt.Errorf("获取分数失败: %v", err)
|
||
}
|
||
return score, nil
|
||
}
|
||
|
||
// ==================== JSON序列化操作 ====================
|
||
|
||
// SetJSON 将结构体序列化为JSON并存储
|
||
func (r *RedisClient) SetJSON(key string, data interface{}, expiration time.Duration) error {
|
||
jsonData, err := json.Marshal(data)
|
||
if err != nil {
|
||
return fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return r.Set(key, jsonData, expiration)
|
||
}
|
||
|
||
// GetJSON 获取JSON并反序列化到结构体
|
||
func (r *RedisClient) GetJSON(key string, result interface{}) error {
|
||
data, err := r.Get(key)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
err = json.Unmarshal([]byte(data), result)
|
||
if err != nil {
|
||
return fmt.Errorf("JSON反序列化失败: %v", err)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// ==================== 分布式锁 ====================
|
||
|
||
// TryLock 尝试获取分布式锁
|
||
func (r *RedisClient) TryLock(key string, expiration time.Duration) (bool, error) {
|
||
success, err := r.Client.SetNX(r.Ctx, key, "locked", expiration).Result()
|
||
if err != nil {
|
||
return false, fmt.Errorf("获取锁失败: %v", err)
|
||
}
|
||
return success, nil
|
||
}
|
||
|
||
// ReleaseLock 释放分布式锁
|
||
func (r *RedisClient) ReleaseLock(key string) error {
|
||
// 使用Lua脚本确保原子性操作
|
||
script := `
|
||
if redis.call("get", KEYS[1]) == ARGV[1] then
|
||
return redis.call("del", KEYS[1])
|
||
else
|
||
return 0
|
||
end
|
||
`
|
||
result, err := r.Client.Eval(r.Ctx, script, []string{key}, "locked").Result()
|
||
if err != nil {
|
||
return fmt.Errorf("释放锁失败: %v", err)
|
||
}
|
||
if result.(int64) == 0 {
|
||
return fmt.Errorf("锁已释放或不属于当前客户端")
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// ==================== 管道操作 ====================
|
||
|
||
// Pipeline 执行管道操作
|
||
func (r *RedisClient) Pipeline(fn func(pipe redis.Pipeliner) error) error {
|
||
pipe := r.Client.Pipeline()
|
||
err := fn(pipe)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
_, err = pipe.Exec(r.Ctx)
|
||
return err
|
||
}
|
||
|
||
// ==================== 事务操作 ====================
|
||
|
||
// Watch 监视键并执行事务
|
||
func (r *RedisClient) Watch(fn func(tx *redis.Tx) error, keys ...string) error {
|
||
err := r.Client.Watch(r.Ctx, fn, keys...)
|
||
if err != nil {
|
||
return fmt.Errorf("事务执行失败: %v", err)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// ==================== 发布订阅 ====================
|
||
|
||
// Publish 发布消息
|
||
func (r *RedisClient) Publish(channel string, message interface{}) error {
|
||
err := r.Client.Publish(r.Ctx, channel, message).Err()
|
||
if err != nil {
|
||
return fmt.Errorf("发布消息失败: %v", err)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// Subscribe 订阅频道
|
||
func (r *RedisClient) Subscribe(channels ...string) *redis.PubSub {
|
||
return r.Client.Subscribe(r.Ctx, channels...)
|
||
}
|
||
|
||
// ==================== 数据库操作 ====================
|
||
|
||
// SelectDB 切换数据库
|
||
// 注意:go-redis/v9的Client没有直接的Select方法,需要通过Do命令执行
|
||
func (r *RedisClient) SelectDB(db int) error {
|
||
// 使用Do命令执行SELECT
|
||
cmd := redis.NewCmd(r.Ctx, "SELECT", db)
|
||
err := r.Client.Process(r.Ctx, cmd)
|
||
if err != nil {
|
||
return fmt.Errorf("切换数据库到 %d 失败: %v", db, err)
|
||
}
|
||
|
||
// 检查命令执行结果
|
||
_, err = cmd.Result()
|
||
if err != nil {
|
||
return fmt.Errorf("切换数据库到 %d 失败: %v", db, err)
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
//// 主函数
|
||
//func main() {
|
||
//}
|