go-redis执行Lua脚本必须用redis.NewScript封装脚本,KEYS须为非空[]string(如["mykey"]),ARGV中数字需转字符串传,返回值须用switch类型断言安全解包,避免panic或静默失败。

go-redis 执行 Lua 脚本不是“写完脚本就能跑”,关键在于参数怎么传、错误怎么判、返回值怎么拆——错一个环节,EVAL 就会静默失败或 panic。
KEYS 必须是非空字符串切片,不能是 nil 或 []string{}
本地单机 Redis 对 keys 是否为空不敏感,但 Redis Cluster 强制要求至少一个 key 用于 slot 路由。传 nil 或空切片 []string{},集群直接报 ERR Error running script (call to f_): @user_script:1: wrong number of arguments,看似参数错,实为 key 缺失。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
-
keys参数永远用[]string{"mykey"}这种显式非空切片,哪怕脚本只读一个 key - 真不需要操作 key(比如纯计算或调
redis.call("TIME")),改用SCRIPT LOAD+EVALSHA,并传一个占位 key(如"__cluster_routing_key__")满足路由要求 - 别在测试时用单机环境验证后就上线,集群行为不兼容
ARGV 里数字要转成 string 再传,Lua 侧再 tonumber()
Go 的 int64、float64 直接塞进 args 切片,Redis Lua 环境收到的是 table(Go 的 interface{} 序列化结果),不是原生 number。脚本里直接 ARGV[1] + 1 会触发 attempt to perform arithmetic on a table value 错误。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 所有数字类参数,在 Go 侧先
fmt.Sprintf("%d", n)或strconv.FormatInt(n, 10)转成字符串再进args - Lua 脚本里统一用
tonumber(ARGV[i])转换,加or 0防空 - 布尔值同理:Go 传
"true"/"false",Lua 用ARGV[i] == "true"判断
返回值必须用类型开关解包,别碰 .Result() 或强转
client.Eval(...).Result() 会把 nil 自动转成空字符串,掩盖真实状态;而直接 cmd.Val().(string) 在脚本返回数字时直接 panic。Redis 返回什么,Val() 就是什么原始类型:nil、int64、string、[]interface{},没有自动兜底。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 永远先检查
err := cmd.Err(),非nil就别碰Val() - 用
switch v := cmd.Val().(type)显式分支处理:case string:、case int64:、case []interface{}:、case nil: - 返回数组时,每个元素仍是
interface{},需递归判断类型,例如v[0].(string)或v[1].(int64)
用 redis.NewScript 封装,别裸写 Eval
每次裸调 client.Eval(ctx, scriptStr, keys, args) 都会发完整脚本文本,浪费带宽、触发 AOF 膨胀、无法利用 Redis 的 SHA1 缓存。更糟的是,出错时没法按脚本名分类日志或监控。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 用
redis.NewScript(luaScript)预定义脚本对象,复用同一实例多次调用 - 调用时用
script.Eval(ctx, client, keys, args),内部自动走EVALSHA,失败 fallback 到EVAL - 脚本内容提取为常量,加注释说明每个
KEYS[i]和ARGV[i]含义,避免半年后自己都看不懂
redis.pcall 返回的错误结构——它不中止脚本,但返回的是 {err="..."} 这样的 Lua table,Go 侧拿到的是 map[string]interface{},不是 error 类型。你得手动检查 v["err"] != nil,而不是依赖 cmd.Err()。这点在做 fallback 逻辑(比如 key 不存在就初始化)时,极易漏判。

















