package redisx import ( "context" "errors" "fmt" "strconv" "time" "github.com/redis/go-redis/v9" ) // ---------------- 基础方法 ---------------- // Set 设置任意 key func Set(key string, value interface{}, expire time.Duration) error { return Client().Set(context.Background(), key, value, expire).Err() } // Get 获取任意 key 的值,返回 string func Get(key string) (string, error) { val, err := Client().Get(context.Background(), key).Result() if errors.Is(err, redis.Nil) { return "", nil } return val, err } // Delete 删除任意 key func Delete(key string) error { return Client().Del(context.Background(), key).Err() } // Exists 判断 key 是否存在 func Exists(key string) (bool, error) { cnt, err := Client().Exists(context.Background(), key).Result() if err != nil { return false, err } return cnt > 0, nil } // SetUserSpaces 初始化用户空间列表(spaceID -> role) func SetUserSpaces(ctx context.Context, userID int64, spaces map[int64]int32) error { key := fmt.Sprintf("user:%d:spaces", userID) pipe := Client().TxPipeline() // 1. 先清空旧数据 pipe.Del(ctx, key) // 2. 再写入新数据(如果有) if len(spaces) > 0 { data := make(map[string]interface{}, len(spaces)) for spaceID, role := range spaces { data[strconv.FormatInt(spaceID, 10)] = role } pipe.HSet(ctx, key, data) } // 3. 执行 _, err := pipe.Exec(ctx) return err } // AddOrUpdateUserSpace 添加或更新单个空间的角色(增量更新) func AddOrUpdateUserSpace(ctx context.Context, userID, spaceID int64, role int32) error { key := fmt.Sprintf("user:%d:spaces", userID) return Client().HSet(ctx, key, strconv.FormatInt(spaceID, 10), role).Err() } // GetUserSpaces 获取用户所有空间列表和角色 func GetUserSpaces(ctx context.Context, userID int64) (map[int64]int, error) { key := fmt.Sprintf("user:%d:spaces", userID) result, err := Client().HGetAll(ctx, key).Result() if err != nil { return nil, err } spaces := make(map[int64]int, len(result)) for k, v := range result { spaceID, err1 := strconv.ParseInt(k, 10, 64) role, err2 := strconv.Atoi(v) if err1 != nil || err2 != nil { continue } spaces[spaceID] = role } return spaces, nil } // GetUserSpaceRole 获取用户在指定空间的角色 func GetUserSpaceRole(ctx context.Context, userID int64, spaceID int64) (role int, exists bool, err error) { key := fmt.Sprintf("user:%d:spaces", userID) val, err := Client().HGet(ctx, key, strconv.FormatInt(spaceID, 10)).Result() if err != nil { if errors.Is(err, redis.Nil) { return 0, false, nil // 用户不在空间 } return 0, false, err } role, err = strconv.Atoi(val) if err != nil { return 0, false, err } return role, true, nil } // RemoveUserSpace 从用户缓存中删除一个空间(用户退出或被踢) func RemoveUserSpace(ctx context.Context, userID int64, spaceID int64) error { key := fmt.Sprintf("user:%d:spaces", userID) return Client().HDel(ctx, key, strconv.FormatInt(spaceID, 10)).Err() } // ClearUserSpaces 删除用户的所有空间列表 func ClearUserSpaces(ctx context.Context, userID int64) error { key := fmt.Sprintf("user:%d:spaces", userID) return Client().Del(ctx, key).Err() } func InSpace(ctx context.Context, userID, spaceID int64) (bool, error) { key := fmt.Sprintf("user:%d:spaces", userID) return Client().HExists(ctx, key, strconv.FormatInt(spaceID, 10)).Result() } // HasUserSpaces 判断用户是否在 Redis 中有空间缓存 func HasUserSpaces(ctx context.Context, userID int64) (bool, error) { key := fmt.Sprintf("user:%d:spaces", userID) // HLen 返回 hash 的字段数量 cnt, err := Client().HLen(ctx, key).Result() if err != nil { return false, err } return cnt > 0, nil }