关于 Go 在 `Return Nil or Pointer to Empty Struct on Error` 上的讨论?

2022-08-12 11:47:48 +08:00
 ryalu
type User struct {}


// 1. return nil
func GetUser() (*User, err) {
	....
    
    return nil, err
}

// 2. return pointer to empty struct
func GetUser() (*User, err) {
	....
    
    return &User{}, err
}

个人会担心下游的不注意( nil 判断)导致进程 panic ,所以基本都是用第二种。想听听大家的意见或见解?

4584 次点击
所在节点    Go 编程语言
82 条回复
lysS
2022-08-12 14:16:28 +08:00
当然 1 了、优先处理 error ,这种写法肯定是错误的:
r, err := do()
r.Xxxx()
if err != nil {
xxxx
}

第二种写法,虽然调用 r.Xxxx()不会 panic ,但是
执行预期是什么喃?完全就会把不确定性传递下去。
ryalu
2022-08-12 14:19:06 +08:00
@liuxu #20 受教了 🌹
ruanimal
2022-08-12 15:04:02 +08:00
@liuxu rust 的方案相对更好,golong 容易 repeat your self
pastor
2022-08-12 15:08:18 +08:00
@ruanimal 并不觉得哪个比另一个更好。如果只是 if err 就嫌麻烦,那其他哪个语言的额外处理是能省略掉的呢?都省不掉,偏偏觉得 if err 就麻烦了,这有点自欺欺人了。
fioncat
2022-08-12 15:09:50 +08:00
可以多看看官方库或是一些著名开源项目的源代码,看他们是怎么做的。
至少在这个问题上,一般的选择都是 1 ,不同理由楼上都给出来了。
pastor
2022-08-12 15:12:51 +08:00
@ryalu 估计 OP 还没 get 到本质,这个问题的本质很简单:golang 提倡的正确做法是 if err ,OP 没有按照正确的做法去做、然后想出了方案 2 去弥补自己错误做法,然后又引来了默认空结构体可能造成的下游错误需要去弥补。

本来就是使用 if err 判断就完事了,入乡随俗、用这个语言就按这个语言的规矩来,根本不需要 #20 对比的其他语言的那么多原因,但是解释 go 自己这样做的原因是合理的。但是话说回来,对比一下多个语言,也让大伙多长长见识,挺好,#20 我先赞为敬
@liuxu
Leviathann
2022-08-12 15:13:32 +08:00
最后我们又一次重新发明了 Monad
nuk
2022-08-12 15:26:28 +08:00
2 吧,不过我只是用的方便,带名字的返回值直接 return 方便,有 err 的话返回的东西就不应该访问,所以都不清理的,不过有时候返回值里的垃圾数据反而会让 debug 会更容易。
rrfeng
2022-08-12 15:30:15 +08:00
如果上下层都是我写,我会用 1 ,强制自己检查 error 。
如果是别人用,我听他的意愿,但是要保证所有地方一样。不能既有 1 又有 2.
如果是我用别人的,我说了不算,只能尽量都检查 error 。
Jooooooooo
2022-08-12 15:31:11 +08:00
1 是更合理的, 无论从语义还是处理上.
janxin
2022-08-12 15:38:51 +08:00
2 会更容易产生被忽略的 bug ,有个类似的问题我们之前遇到过的是我们的 err wrapper 的接受 err 为空 nil ,返回为 nil 。但是一般这种场景很多时候会需要返回错误,导致了很多隐性 bug ,我们扫了一遍找到了几百个错误使用.。。
xhxhx
2022-08-12 16:32:37 +08:00
不能害怕 panic ,panic 发现的越晚,造成的影响越大
asmoker
2022-08-12 16:43:09 +08:00
```go
// 3. return nil, nil
func GetUser() (*User, err) {
....

return nil, nil
}
```

会不会这样?查询也没有报错,确实也没有这个用户,后续走创建用户的逻辑(假设有的话)。还是说 err 返回一个比如说 `error('用户不存在')` 这样的,caller 通过比对 err 进行下一步逻辑?🤔
zhuweiyou
2022-08-12 16:45:43 +08:00
在其它语言里,我一般的做法是抛异常. 所以在 go 里应该是返回 err 判断 err 选 1.
pkoukk
2022-08-12 17:44:33 +08:00
1 ,如果下游可以容忍错误,也应该是下游自己创建一个&User{}
ElmerZhang
2022-08-12 17:59:22 +08:00
选 1
nil 才是不存在,空值和不存在是两回事
charmToby
2022-08-12 18:02:09 +08:00
1, 有错误都必须处理
yazinnnn
2022-08-12 18:04:27 +08:00
学 haskell 少走 30 年弯路
学 lisp 少走 60 年弯路
ryalu
2022-08-12 18:10:21 +08:00
@pastor #26 我的错,可能我的表达能力有所欠缺。我想说的侧重点不是在 err 上,而是在于 if err 校验成功后,是否需要对 *User 这样一个返回值去做 if user == nil 校验。个人选择 2 的想法是在下游可以放心大胆的直接 *User, 而不是 err 校验为空后,再继续对 if user == nil 做一次校验
sardina
2022-08-12 18:56:00 +08:00
都出现 err 还用返回值不是作死吗

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/872400

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX