Golang Redis存储层Get方法如何正确返回EntityNotFound错误
Go 操作 Redis 区分「实体不存在」和「数据库错误」的实现方案
主流 Go Redis 客户端都已经内置了 key 不存在场景的专属错误常量,不需要自行匹配错误文本,直接通过标准库的错误判定方法即可精准区分两类场景。
核心实现逻辑(以社区主流 go-redis v8/v9 为例)
当执行GET命令查询不存在的 key 时,客户端会固定返回redis.Nil错误,你只需要用errors.Is对返回错误做判定即可,参考实现:
import ( "context" "encoding/json" "errors" "fmt" "github.com/redis/go-redis/v9" // v8版本导入路径为"github.com/go-redis/redis/v8" ) // 预定义业务层错误 var ErrEntityNotFound = errors.New("entity not found") var ErrDBOperation = errors.New("db operation failed") type EntityRepo struct { client *redis.Client } type Entity struct { ID string `json:"id"` Name string `json:"name"` } func (r *EntityRepo) Get(ctx context.Context, entityID string) (*Entity, error) { key := fmt.Sprintf("entity:%s", entityID) val, err := r.client.Get(ctx, key).Result() if err != nil { // 优先判定key不存在场景 if errors.Is(err, redis.Nil) { return nil, ErrEntityNotFound } // 其余错误统一归为数据库操作错误 return nil, fmt.Errorf("%w: %v", ErrDBOperation, err) } // 反序列化拿到实体 var e Entity if err := json.Unmarshal([]byte(val), &e); err != nil { return nil, fmt.Errorf("%w: unmarshal failed: %v", ErrDBOperation, err) } return &e, nil }
其他客户端适配说明
如果你用的是老牌 Redigo 客户端,逻辑完全一致,只是对应的不存在错误常量为redis.ErrNil,判定代码片段如下:
// Redigo 客户端判定示例 conn := redisPool.Get() defer conn.Close() val, err := redis.Bytes(conn.Do("GET", key)) if err != nil { if errors.Is(err, redis.ErrNil) { return nil, ErrEntityNotFound } return nil, fmt.Errorf("%w: %v", ErrDBOperation, err) }
注意事项
- 禁止通过匹配错误文本(比如判断
err.Error() == "redis: nil")的方式做判定,客户端版本迭代时错误文本可能变更,用官方暴露的错误常量才能保证向前兼容 - 错误判定顺序不能颠倒:必须先判定key不存在的专属错误,再归类其他数据库错误,否则会把不存在场景误判为通用DB错误
- 如果你使用的是其他二次封装的Redis ORM/工具类,直接查阅其文档中暴露的Nil/KeyNotFound类错误常量即可,判定逻辑完全相同
内容的提问来源于stack exchange,提问作者Umang Mundhra
相关产品推荐
相关产品推荐

