一般情况下需要串行化的执行下去,如果其中一步遇到错误就会退出,但这样调用完个每个方法都要写个 err
如果将执行的方法作为一个闭包封装进去,就可以省去一大堆 if err:
这样如果执行的过程中遇到了错误,也会跳过执行, 最后调用 wrap.Error()返回错误 e.g.:
外层变量 a,b,c,d 可以通过闭包来赋值
1
rrfeng 2023-04-28 15:46:28 +08:00
没变少啊……
|
2
chanyan 2023-04-28 15:47:23 +08:00
|
3
sduoduo233 2023-04-28 15:49:07 +08:00 via Android
这样怎么确定 err 是在哪一步抛出的?
|
4
learningman 2023-04-28 17:17:14 +08:00 via Android
你这写的比 if err 还多
|
5
ljsh093 2023-04-28 17:20:35 +08:00
还是 4 行一个啊
|
6
777777 2023-04-28 17:24:07 +08:00 10
就我一个人喜欢写 if err ?简单直接
|
7
blackvv666 2023-04-28 17:26:57 +08:00
自己用用可以
|
8
hahasong 2023-04-28 17:31:35 +08:00
这还不如用 defer 呢 有种用 java 面向对象打印 hello world 即视感
|
9
hzzhzzdogee 2023-04-28 17:41:11 +08:00
其实应该是 wrap?
|
10
zhangxh1023 2023-04-28 17:47:30 +08:00 2
没了 if err 的 golang 都没那味儿了
|
11
helloit 2023-04-28 17:49:49 +08:00
errors := map[string]string{
"a": "a error", "b": "b error", "c": "c error", "d": "d error" } |
12
magicdawn 2023-04-28 17:50:21 +08:00 via Android
rust 也是 err value ,但是有 unwrap 和 ?存在方便许多
|
13
fgwmlhdkkkw 2023-04-28 17:51:26 +08:00
```
func Must[T any](T val, e error) T { if e != nil { painc(e) } return val } func Must2[T any, K any](T val1, K val2, e error) (T, K) { if e != nil { painc(e) } return val1, val2 } ``` |
14
fgwmlhdkkkw 2023-04-28 17:52:52 +08:00
@fgwmlhdkkkw 😓 哈哈哈哈,,搞混了
|
15
cassyfar 2023-04-28 17:54:33 +08:00
人才
|
16
cholerae 2023-04-28 17:55:20 +08:00 2
|
17
Leviathann 2023-04-28 18:10:49 +08:00
@magicdawn rust 是 value or error 不是 value and error
|
18
TWorldIsNButThis 2023-04-28 18:16:51 +08:00
|
19
dobelee 2023-04-28 18:24:03 +08:00
一行没变少,反而增加几行初始化变量。。
|
21
totoro52 2023-04-28 18:27:23 +08:00
与其叫少写,不如叫遮羞布。。。
|
23
voidmnwzp OP |
24
elechi 2023-04-28 18:46:20 +08:00
好像有个 multierr 包
|
25
RedisMasterNode 2023-04-28 20:35:29 +08:00
觉得 if err != nil 让别人更容易搞懂程序每一步的错误想怎么处理...不明白为何要把它 warp 或者简化起来
|
26
ck65 2023-04-28 20:39:36 +08:00
字面意义上的过度封装。
|
27
flyqie 2023-04-28 21:02:47 +08:00
|
28
hsfzxjy 2023-04-28 21:05:26 +08:00 via Android
虽然但是,为什么是 warp 不是 wrap
|
29
cmdOptionKana 2023-04-28 21:14:19 +08:00
我也有做类似的处理
// WrapErrors 把多个错误合并为一个错误. func WrapErrors(allErrors ...error) (wrapped error) { for _, err := range allErrors { if err != nil { if wrapped == nil { wrapped = err } else { wrapped = fmt.Errorf("%w | %w", wrapped, err) } } } return } |
30
cmdOptionKana 2023-04-28 21:16:46 +08:00
我这个使用时应该更直白简洁, 例如
a, err1 := func1() b, err2 := func2() if err := WrapErrors(err1, err2); err != nil { return err } |
31
zbinlin 2023-04-28 21:40:33 +08:00 1
这时候不应该换语言了吗 🐶
|
32
SenLief 2023-04-28 22:06:19 +08:00 1
if err 都没有,那还是 go 了吗?
|
33
piaodazhu 2023-04-28 22:26:57 +08:00
想到个这个,大家看这样有什么问题不:
1. 定义一个函数 func checkError(err error),函数内检查如果 err!=nil 就 panic(err) 2. 在你业务函数开头写一个 defer func()内部做 recover() 3. 在你业务函数中每次调用后,调用 checkError(err) 这样就不用写那么多`if err != nil { ... `了吧,panic 被捕获时,也能知道发生 err 的是啥。 |
34
yazinnnn 2023-04-28 23:02:45 +08:00 via Android 2
是我第 2887 喜欢的 go boy 重新发明 monad 时间🤗
|
35
Kisesy 2023-04-28 23:08:13 +08:00
@cmdOptionKana 楼主要的效果是,有函数有错误,下面的代码就不执行了,你这个即使 func1 出错了,func2 还是会执行
|
36
voidmnwzp OP @piaodazhu 可以是可以 这样就是类似 java 的 try/catch 但是,风险太大 万一哪个地方漏写了 recover 那不是单个 goruntine down 了 是个整个进程都得挂 一不小心就是线上重大事故了属于
|
40
magicdawn 2023-04-29 17:21:49 +08:00
|
42
magicdawn 2023-04-29 17:47:10 +08:00
|
43
voidmnwzp OP |
44
fregie 2023-04-30 10:12:11 +08:00 via Android
golang 都迭了这么多代了,仍然一点没改错误处理机制,大概谷歌那帮开发 golang 的专家没有这里的评论者考虑的周全吧,为什么不加 try-catch 呢?
从对 golang 的理解就可以看出各位到底是一位优秀的 coder 还是一位优秀的 engineer coder 会从自己的角度出发,觉得写起来最方便最快的就是好的 engineer 会从工程的角度出发,考虑如何能让工程的效率和质量更好 现代大型软件的业务逻辑 bug ,绝大多数都是因为错误处理不得当导致的,各位 coder 不妨回想一下最近一年遇到的 bug ,是不是如此。 这种又臭又长的错误处理机制,虽然烦人,但是有效 |
46
voidmnwzp OP @fregie 我认为 error is value 的设计并无不妥 只是实际业务中每一个 err 都需要去 if err 处理 太麻烦 不处理万一出现问题 那是找死都找不出来的
|
47
ireina 2023-05-26 02:06:48 +08:00
我也尝试过类似的事。我觉得没必要去改`if err != nil`其实,错误处理是一种计算效应,真正的干净的代码需要 monad ,但是目前没几个语言直接支持 monad 的上下文管理。把 error wrap 起来的确是一种处理错误的方式,标准库里其实也有使用过(但是很少),这种方式的缺点在于你必须很清楚 error 的状态是如何共享的。我觉得在给 interface 写 adapter 的时候可以用,但是平时写 struct 是不必要的。
|