Golang Go语言中,获取一条记录,数据库找不到记录,是返回特殊的 error 还是返回 nil,error 也返回 nil 吗

发布于 1周前 作者 bupafengyu 来自 Go语言

golang ,获取一条记录,数据库找不到记录,是返回 error 还是 返回对象 nil , error 也返回 nill

比如用用户 ID 获取用户资料

我是返回一个特殊的 error

func (* UserModel) GetUser(uid uint) user User, err error {
   ....
   return user, ErrorNotFound
}

还是返回 nil, nil

func (* UserModel) GetUser(uid uint) user *User, err error {
   ....
   return nil, nil
}

Golang Go语言中,获取一条记录,数据库找不到记录,是返回特殊的 error 还是返回 nil,error 也返回 nil 吗

更多关于Golang Go语言中,获取一条记录,数据库找不到记录,是返回特殊的 error 还是返回 nil,error 也返回 nil 吗的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

27 回复

我选 nil, nil

更多关于Golang Go语言中,获取一条记录,数据库找不到记录,是返回特殊的 error 还是返回 nil,error 也返回 nil 吗的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


通常是这么来的。

func (* UserModel) GetUser(uid uint) user User, err error {

return nil, nil
}

func (
UserModel) MustGetUser(uid uint) user User, err error {

return user, ErrorNotFound
}

我也喜欢 nil,nil 这种 不过我刚开始用 golang ,所以比较不确定。。

好像也可以,不过一般不会定义两个功能几乎一样的方法吧。。

user=nil,err=errors.New(“user not found”)
return;

error 应该返回 nil

这个问题在于 GetUser 没有找到用户,到底算不算一种 error ,就看你的定义了
如果算 error ,一个比较麻烦的地方是,按照 go 的哲学,所有 error 都要明显的 check
在检测错误的时候,你还需要排除 ErrorNotFound 这种情况,就比较繁琐


Must 开头的函数应该不返回错误,有错误就 panic

我使用第二种,在实际项目中每个错误码都是特定的,查询错误是 ErrGetData ,数据不存在是 ErrDataNotExist ,以此类推。这个错误码不是字符串,而是一个对象
type errorCode {
ID string
Namespace string
Code int32
Message string
}

返回 nil ,不管啥语言,不要在内部乱抛出异常

这里看你对错误的定位
我是这样想的(做的) 看这个方法具体面对的层级
如果只是在数据库访问层级 返回 nil 肯定是比 err 合理 因为对于数据库本身来说 就是没有查到数据而不是产生了错误
但是对于业务处理层来说 可能拿到了 nil 以后需要返回一个 err 来通告操作的人

nil,nil

实现简单,不用费事的区分开数据库错误还是不存在。
否则还需要定义不同的 error 来区分是数据库错误还是不存在。

mgo 是返回 ErrNotFound

如果返回 nil,nil 那么,每次得到的 user 还得检查是否 nil ,而如果你查到到的 error 为 nil 的话,那么 user 可能有值

user 肯定有值,打快了,敲错字了



Must 一般是 panic 吧

return user, ErrorNotFound

另外其实 golang 中的 error 是个 interface ,所以利用 提到的错误扩展方式其实非常方便

我觉得这种问题没什么好纠结的。

返回 error 是考虑到后面的过程能截获这个错误然后进行处理,而标记成 Must 的函数则是这个函数出现错误之后,程序完全没必要继续运行下去了。

GetUser 找不到记录的话,应该返回 nil 指针附带一个错误,指明发生了什么(比如是什么导致无法获取用户的,是没有记录,服务器挂了,服务器拒绝处理还是其他什么)。你可以参考 Google 在自己 AppEngine 系统上的实现:
https://cloud.google.com/appengine/docs/go/datastore/reference#variables

当 Datastore 尝试获取一个不存在的对象时,会返回 ErrNoSuchEntity 这个 error 。

这个跟你业务场景,以及设计有关,建议用 2 ,否则给自己留坑,不信你试试
如果用 2 的话,可以在调用函数时区分出到底是同 db 交互失败,还是交互成功但却查询为空,可以在调用时区别地对待这两种结果……
不信你试试 1 ……

查询结果为空,返回 not found ,与数据交互出现的无知,直接返回上级错误

这两种在区分功能上并没有区别吧

我认为,
如果系统其他部分可能会报错,比如数据库可能连接不上, cache 可能挂了什么的,那返回值就需要第二个 error 参数
如果系统其他部分根本不可能报错,就是一个普普通通的数据类型,没有跟其他系统交互,那么就没有第二个 error 返回,找不到就直接一个 nil 就好了, nil 本身就是找不到的意思,互为充分必要条件。
至于返回是否是 nil 的检查,我想应该适当的抛给上层逻辑来处理。具体情况具体分析。

我也纠结过,现在的做法是:

定义一个UserNotFound的空 User struct ,如果查询没有结果,就返回UserNotFound, nil

给 User 这个 struct 定义一个IsNil()的方法,一般来说用户名不能为空,所以就根据用户名来判断这个 user 是不是存在

handler 里,如果user.IsNil()结果是 true ,就返回 404

在Go语言(Golang)中处理数据库操作时,当尝试获取一条记录但数据库找不到该记录时,通常的最佳实践是返回一个非nilerror对象,同时这个error对象应明确表示记录未找到的情况,而不是返回nil

返回nilerror通常意味着操作成功且没有发生任何错误。如果数据库查询未能找到记录,这实际上是一个有效的查询结果,但并不是一个错误情况(比如连接失败或查询语法错误等)。然而,为了区分“记录不存在”这一预期内的结果和其他潜在的错误,应返回一个特定的错误值,这有助于调用者更准确地处理这种情况。

一种常见做法是使用自定义错误类型或特定的错误消息来表示记录未找到的情况。例如,你可以定义一个RecordNotFound错误类型或使用一个包含特定错误消息的errors.New("record not found")。这样,调用者可以通过类型断言或检查错误消息来判断是否是因为记录不存在而导致的错误,从而采取适当的行动,如返回默认值、提示用户等。

总之,对于数据库查询未找到记录的情况,应返回一个非nilerror对象,以清晰表示这一特定情况,而不是简单地返回nil。这种做法提高了代码的健壮性和可维护性。

回到顶部