Go中redis.Client.Eval参数顺序为script、keys、args,keys和args必须是[]interface{}切片且元素为字符串或合法类型,空keys需传空切片而非nil,Lua中用KEYS[1]、ARGV[1]访问。

Go 用 redis.Client.Eval 执行 Lua 脚本必须传对参数顺序
Go 的 redis.Client.Eval 不是「脚本 + key + arg」三段式,而是 script, keys, args 三参数,且 keys 和 args 都是 []interface{} 类型切片——但 Redis Lua 环境里只认 KEYS[1]、ARGV[1],不会自动解包。常见错误是把 key 当字符串传进去,结果 Lua 里 KEYS 是空表。
-
keys切片里的每个元素,会按顺序映射为 Lua 中的KEYS[1]、KEYS[2]…,必须是字符串(string类型) -
args切片同理,对应ARGV[1]、ARGV[2]…,可以是字符串、数字、甚至nil(Go 里用interface{}(nil)) - 如果脚本不操作 key(比如纯计算),
keys传空切片[]interface{},不能传nil,否则Eval会 panic
示例:原子增并限流
script := "if redis.call('incr', KEYS[1]) == 1 then redis.call('expire', KEYS[1], ARGV[1]) end return redis.call('get', KEYS[1])"
result, err := client.Eval(ctx, script, []interface{}{"rate:uid:123"}, []interface{}{60}).Result()
Lua 脚本里调 redis.call 失败会直接中断,别指望 try-catch
Redis 的 Lua 没有异常捕获机制。redis.call 报错(比如 key 类型不对、命令不存在)会导致整个脚本终止,并返回错误给 Go。而 redis.pcall 会捕获错误并返回 {err="..."} 表,适合需要 fallback 的场景。
- 用
redis.call:你确定所有前置条件都满足(key 存在、类型正确、命令可用),失败即业务异常 - 用
redis.pcall:想自己处理错误,比如“key 不存在就初始化”,但注意它返回的是 Lua 表,Go 侧要解析map[string]interface{}或用redis.Cmd.Val()做类型断言 - 别在 Lua 里写耗时循环或正则——Redis 是单线程执行 Lua,卡住就阻塞所有请求
Go 侧处理 Eval 返回值得看清楚类型,不是所有都返回 string
client.Eval(...).Result() 的返回类型取决于 Lua 脚本最后一行的值:返回数字 → Go 得用 int64 接;返回数组 → 是 []interface{};返回 nil → nil;返回布尔 → bool。直接强转 string 会 panic。
立即学习“go语言免费学习笔记(深入)”;
- 安全做法:用
cmd.Val()拿原始 interface{},再做类型 switch - 如果脚本固定返回整数(如
return #redis.call('lrange', ...)),用cmd.Int64()更稳妥 - 返回数组时,每个元素仍是
interface{},可能嵌套 string/int64/nil,需逐层判断
示例:
val, err := client.Eval(ctx, "return {1, 'ok', nil}", nil, nil).Result()
// val 是 []interface{}{int64(1), "ok", nil}
本地开发调试 Lua 脚本,别只靠 Go 代码反复试
写错一行 Lua 就得改 Go、编译、跑,效率极低。应该先用 redis-cli --eval 在终端直连验证脚本逻辑和参数行为。
- 命令格式:
redis-cli --eval script.lua key1 key2 , arg1 arg2(逗号前后空格不能少) - 注意:CLI 里
KEYS和ARGV是字符串数组,和 Go 传参一致,能提前暴露类型错、下标越界等问题 - 脚本里加
redis.log(redis.LOG_WARNING, "debug: "..json.encode({...}))(需加载 json 库)可打日志,但生产禁用
真正难的不是语法,是理解 Redis 执行上下文——KEYS 必须是真实存在的 key 名(不是变量名),ARGV 不能带空格除非引号包裹,还有 EVALSHA 缓存命中率这些细节,一不留神就掉坑里。


















