Lua脚本返回false时Redis EvalSha报错"redis: nil"如何解决?
解决方案
问题根源
Redis与Lua脚本的返回值存在固定类型映射规则:
- Lua的
false或nil会被序列化为Redis的nil类型; - Lua的
true会被序列化为Redis的整数1;
Go的redis客户端(如go-redis)调用.Result()方法时,会将Redis的nil解析为redis.Nil错误,这就是返回false时触发报错的原因。另外原代码中rs.(bool)的类型断言存在逻辑漏洞:Lua返回true时,客户端实际拿到的是int64(1),断言会失败,最终返回布尔零值false。
正确处理代码
方式1:用Scan简化类型转换
import "errors" import "github.com/go-redis/redis/v8" func (rc *redisClient) runDummyScript(ctx context.Context) bool { scriptSha, err := rc.ScriptLoad(ctx, dummyScript).Result() if err != nil { return false } var ans bool err = rc.EvalSha(ctx, scriptSha, []string{}).Scan(&ans) if err != nil { // Redis nil对应Lua返回false/nil if errors.Is(err, redis.Nil) { return false } fmt.Print("could not execute the redis commands for ", err) return false } return ans } const dummyScript = `return false`
方式2:手动处理类型与错误
import "errors" import "github.com/go-redis/redis/v8" func (rc *redisClient) runDummyScript(ctx context.Context) bool { scriptSha, err := rc.ScriptLoad(ctx, dummyScript).Result() if err != nil { return false } rs, err := rc.EvalSha(ctx, scriptSha, []string{}).Result() if err != nil { if errors.Is(err, redis.Nil) { return false } fmt.Print("could not execute the redis commands for ", err) return false } // 处理Lua返回true对应的int64(1) if val, ok := rs.(int64); ok { return val == 1 } // 兼容其他可能的布尔值场景 if val, ok := rs.(bool); ok { return val } // 非预期返回类型,默认返回false return false } const dummyScript = `return false`
说明
- 两种方式都明确区分了
redis.Nil错误(对应Lua返回false)和真正的执行错误,避免了直接忽略所有错误的不合理方案; Scan方法会自动将Redis的整数1映射为Go的true,简化了类型转换逻辑;- 手动处理类型的方式更灵活,适合需要兼容多种返回类型的复杂场景。
内容的提问来源于stack exchange,提问作者Amit Upadhyay
相关产品推荐
相关产品推荐

