go中zadd必须传redis.z结构体,score需为float64(如95.0),member推荐string;查榜用zrevrangewithscores,索引范围是int64,zrevrank查不到返回-1需显式判断,累加分数须用zincrby避免竞态。

Go 里 ZAdd 必须传 redis.Z 结构体,不能直接传分数和字符串
很多新手一上来就写 rdb.ZAdd(ctx, "rank", 95, "user:123"),直接 panic 或静默失败。go-redis 的 ZAdd 不接受松散参数,必须显式构造 redis.Z 类型:
-
Score字段必须是float64,哪怕整数也得写成95.0,传95(int)或"95"(string)都会出错 -
Member推荐用string,比如"user:123";避免用中文、空格或结构体,否则序列化后查不到 - 重复
ZAdd同一个Member是安全的,自动更新分数,不用先ZREM再加
正确写法:
err := rdb.ZAdd(ctx, "rank:weekly", &redis.Z{Score: 87.5, Member: "user:789"}).Err()
查前 N 名要用 ZRevRangeWithScores,不是 ZRange
排行榜默认要“分数高的排前面”,但 ZRANGE 是升序(分数低的在前),ZREVRANGE 才是降序。更关键的是:不带 WithScores 的版本只返回成员名,没分数——前端常需要一起展示。
- 索引范围是
int64类型,0, 9表示前 10 名(左闭右闭),不是0, 10 - 想取全部数据,第二个参数必须是
int64(-1),不能写-1(在某些环境会被当成大正数) - 如果只调
ZRevRange却没看到数据,先检查是否误用了ZRange,再确认参数类型
推荐封装:
members, err := rdb.ZRevRangeWithScores(ctx, "rank:weekly", 0, 9).Result()
ZRevRank 返回 -1 不代表报错,而是成员不存在
ZRevRank 和 ZRank 都返回 int64,查不到时统一返回 -1,且 err == nil。很多人只判 err 就以为成功了,结果拿到 -1 还当是第 0 名。
- 必须显式判断返回值:
if rank == -1 { /* 用户不在榜上 */ } -
ZRevRank返回的是从 0 开始的索引,展示时要 +1 才是“第几名” - 如果业务允许“未上榜用户显示为‘未进入前 100’”,那就别 panic,按逻辑兜底
并发累加分数必须用 ZIncrBy,别在 Go 层读-改-写
点赞、打赏、活跃度加分这类场景,本质是“在原分基础上加 delta”,不是覆盖。若用 ZAdd 先读再算再写,会丢更新、引入竞态,还多一次网络往返。
-
ZIncrBy是 Redis 原子命令,delta参数必须是float64或能转成字符串的值(如5.0或"-2.5") - 增量为 0 时仍执行,但不会创建新 member——这点和
ZAdd一致 - 混用风险:对同一 member 先
ZIncrBy加了 5 分,再ZAdd写入 100 分,最终就是 100,之前加的全白费
正确姿势:
_, err := rdb.ZIncrBy(ctx, "rank:weekly", 5.0, "user:789").Result()
最易被忽略的点:分数精度和上下文超时。float64 在 Redis 里存的是 IEEE 754,小数可能有微小误差;而 context.WithTimeout 设太短(比如 50ms),网络抖动时 ZRevRange 直接返回空切片,不是错误,容易误判为“没数据”。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











