1
BugCry 2022-07-09 19:32:16 +08:00 via Android
panic/recover 。但是用 Java 的思维写 go ,为什么不直接写 Java ?
|
2
golangLover 2022-07-09 19:34:41 +08:00 via Android 4
不用想了,没有,问就是大道至简
|
3
golangLover 2022-07-09 19:35:49 +08:00 via Android
对了,除了大道至简,还有招人上手容易,一两天就能写代码。
|
4
Trim21 2022-07-09 19:37:25 +08:00
panic/recover (
|
5
wangx0102 2022-07-09 19:38:37 +08:00
感觉就 panic/recover
|
6
LukeEuler 2022-07-09 19:50:58 +08:00 1
https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling-overview.md
官方很早就在思考并设计这块内容了,至于什么时候来,就不知道了。我个人更喜欢 rust 的设计。 |
7
iyaozhen 2022-07-09 21:36:52 +08:00
没有,写 Go 千万不要和 Java 对比,完全不是一个阶段。
|
8
frodez 2022-07-09 21:43:26 +08:00 4
虽说我日常看不惯 go ,但我仍然要问:你为什么需要一个统一的错误处理逻辑?你真的想清楚了原因,而非一时偷懒选择了它?
你或许应该了解到,和错误处理相关的问题永远都包括两个议题:如何正确处理错误,和如何方便地处理错误。但很可惜绝大多数人都混淆了它们,并把它们视为同一个问题。 |
9
frodez 2022-07-09 21:48:41 +08:00
另外,方便地处理错误往往会让程序员有精力正确地处理错误,但不是说方便地处理错误就会让程序员一定能正确地处理错误。另一方面,正确地处理错误在某种程度上可以让错误处理更方便,但跨过了某个分界点后,正确处理错误又不能与方便地处理错误相妥协。所以这必须是一个与实际业务紧密相关的问题,如果不相关,那么你的做法就会既不方便也不正确。
|
11
frodez 2022-07-09 21:57:13 +08:00
@pkupyx 我个人的建议仍然是优先选择正确性。如果真的可以把错误归类为 95%的不需要自己处理的错误,和 5%的需要自己处理的错误,你可以把前者和后者分开,前者一路返回,后者自己专门处理。
不是非常建议使用 panic 和 recover ,因为它们都是函数级别的跳转逻辑——如果你要在循环中处理错误,使用 panic 和 recover 很可能会导致遗漏。 |
12
iseki 2022-07-09 22:08:23 +08:00 via Android
panic 吧,一般可以用这种方法处理的错误,都不是真的能处理的错误,panic 最方便了
|
13
kidlj 2022-07-09 22:14:17 +08:00 via iPhone
写 web 的话,echo 框架有集中处理错误的方式,比如加上 message 字段或者根据 accept header 返回不同的 content-type 数据。在业务 handler 里只需要 return error 就好了。
另外,同意楼上说的,方便的不一定是正确的。Go 的错误处理虽然还有优化空间,但在很多人看来这种方式起码是正确的。 |
14
hallDrawnel 2022-07-10 00:31:32 +08:00 2
正确的做法就是就地判断 error ,当场决定是否要处理。相比抛出异常,有了更合理的处理时机——在错误发生的地方,持有错误发生的上下文信息,可以自由地编写针对性的处理逻辑;而统一的异常处理节点已经丢失了错误发生的上下文信息。赞同 frodez 的说法,统一的逻辑往往就会变得既不方便也不正确。
panic 仅仅应该用在整个程序已经无法继续运行的时候,对于业务逻辑来说很少有这种情况。 |
15
joesonw 2022-07-10 00:32:59 +08:00 via iPhone
@pkupyx err 往上传就是为了在每一层调用的地方加上现场信息,方便查询错误在哪。
无脑往上抛要还原现场就只能抓 stacktrace 了,这样的运行时成本就高了。你要不在乎这个性能损失的话无脑 panic 也是可以的,最外层 recover 抓个 stacktrace 。例如一众 web 框架里面都会有的 Recover 的 middleware 。 |
16
LeslieWongH 2022-07-10 10:59:08 +08:00
插一句,JS 的 try catch 异步函数的替代方案就是模仿 go 的思路,返回[err, data]数组——
参见 NPM 仓库 await-to-js |
17
pkupyx OP @joesonw 然而绝大多数场景就是只有在错误发生的位置抓 stacktrace ,其他层级无脑往上抛。
比如常见的一个服务的调用,展开之后是这个结构: handler.getCompanyAdminList(companyId) (list, err) { // 封装了校验和调用 service // ... list, err := service.getCompanyAdmin( companyId ) (list, err) { // 封装了获取 admin 和拼接 admin 权限 // ... list, err := adminRepo.getCompanyAdmin() (list, err) { // 封装了取 cache 和 orm // ... list, err := orm.getCompanyAdmin() { // 封装 db list, err := db.select() if err!=nil { 1 // log return nil, err } } if err!=nil { 2 return nil, err } // ... // 其他业务代码 } if err!=nil { 3 return nil, err } // ... // 其他业务代码 } if err!=nil { 4 return nil, err } // ... // 其他业务代码 } 只有 1 需要 log ,然后抛出错误到最外层,根据错误直接返回 response 。2 、3 、4 步骤就是无脑略过。 |
18
mekingname 2022-07-11 09:42:04 +08:00 via iPhone
无脑略过的 err ,可以直接用_代替啊。
data, _ = 函数() 也不需要用 if 去判断。 |
19
partystart 2022-07-11 10:15:54 +08:00
|
20
mekingname 2022-07-11 12:14:25 +08:00
@partystart 我忽略的是 err ,又没有忽略 data
|
21
mekingname 2022-07-11 12:15:50 +08:00
|
22
nothingistrue 2022-07-11 16:07:11 +08:00
@frodez 实际上你并不知道,甚至只是了解一下 Java 的异常机制。Java 的异常机制是:该是自己的事就 catch 住自己处理,不是自己的事就 throw 出去。该自己处理的自己处理,不该处理的抛出去而不要隐藏,这是即正确又方便的事。按照你的思路,来了错误不管是不是自己的就硬去处理,那才是不正确的事。
此外,统一的错误处理逻辑也不是偷懒,它要在全局层面管理异常,需要花费更多而不是更少的精力。那种捕获到异常就只提示一个“有错误”的统一错误处理才是偷懒,但这不是全局异常处理专属的,if (err ) then print "有错误",也能这样偷懒。 |
23
frodez 2022-07-11 18:26:12 +08:00
@nothingistrue 你恐怕理解错我的意思了,我没有一句话说过非要自己处理错误,甚至哪怕是不应该自己处理的错误也要自己来处理。而且这和我的意思正相反,因为这不是正确的错误处理方式。
至于统一的错误处理逻辑,统一的错误处理逻辑不会导致必然的错误(但也不等于一定正确),但基本上是更方便的。很多程序员往往混淆了正确处理错误和方便处理错误两件事,因此实际的统一错误处理实践,往往就会通向方便但错误的处理模式。 当然,没有统一的错误处理逻辑,每个错误都必须显式地处理,也不等于必然的正确。就像你说的,if err != nil { print } 也是显式的处理错误方式一样。由于显式处理错误的不方便,就会让很多程序员抵触错误处理,这样也会导致错误。 但在我看来,前者与后者相比,后者起码提供了一个正确且良好的基础,只不过容易因为程序员偷懒而败坏基础。而对于前者,方便比正确更重要,这使得它的基础不够牢固。 所以个人认为,错误处理最好的实践应该是在尽可能显式处理错误的基础上,给程序员提供语法糖、胶水方法、linter 之类的工具,让错误处理变得方便。 |
24
SmiteChow 2022-07-13 18:02:50 +08:00
没有
|