有些错误不需要特殊处理,就能用这些简单方便的函数,有错误就 panic, 无错误就直接返回有用结果:
func Try(err error) {
if err != nil {
panic(err)
}
}
func Try1[V any](val V, err error) V {
Try(err)
return val
}
func Try2[V1 any, V2 any](val1 V1, val2 V2, err error) (V1, V2) {
Try(err)
return val1, val2
}
一个例子:
// 不使用泛型的传统实现
func GetExePath() string {
path, err := os.Executable()
if err != nil {
panic(err)
}
return path
}
// 使用泛型,告别 `if err != nil`
func GetExePath() string {
return Try1(os.Executable())
}
1
sunny1688 2023-03-06 10:35:41 +08:00
比 interface{}强一点
|
2
cnbattle 2023-03-06 10:36:24 +08:00
不喜欢 panic 0.0
|
3
Nazz 2023-03-06 10:38:00 +08:00
看起来还不错
|
4
rrfeng 2023-03-06 10:38:41 +08:00 1
但是大部分时候不想 panic ,还是得造个 Option 好用
|
5
yyf1234 2023-03-06 10:41:48 +08:00 via iPhone 4
写过实际业务没大哥,线上也直接 panic 吗
|
6
yzbythesea 2023-03-06 10:42:41 +08:00
panic 是高手
|
7
voidmnwzp 2023-03-06 10:44:17 +08:00 2
又在玩 java try catch 那套是吧 建议去写 Java
|
8
fengjianxinghun 2023-03-06 10:44:42 +08:00
。。。。any 不就是 interface{}别名么。。
|
9
chiuan 2023-03-06 10:46:45 +08:00
又把多态那些搞进来了吗?
|
10
lance6716 2023-03-06 10:47:03 +08:00 via Android 1
一般叫 must ,你这个跟 try 有一毛钱关系吗
|
11
SuperMild OP @yyf1234 有使用场景的,你看看这个很流行的库也提供了这个函数 https://github.com/samber/lo#must
Must Wraps a function call to panics if second argument is error or false, returns the value otherwise. |
12
sunny1688 2023-03-06 10:50:08 +08:00
@fengjianxinghun interface{}要转类型,泛型不用
|
13
rrfeng 2023-03-06 10:50:16 +08:00 1
楼上说的对,Go 里会写一个 MustXXX() 用来 panic ,比你这个 Try 好。
本身也就是多几行而已 func XXX(){} func MustXXX(){ if XXX() != nil { panic() } } |
14
SuperMild OP @fengjianxinghun 泛型是天生类型安全的,interface{}要自己写一堆判断才能确保类型安全。
|
15
SuperMild OP |
16
dw2693734d 2023-03-06 10:59:55 +08:00
@yyf1234 我就是线上 panic😂,受了 erlang 的 let it crash 的影响
|
17
yyf1234 2023-03-06 11:09:17 +08:00 via iPhone
|
18
SuperMild OP |
19
wtfedc 2023-03-06 11:38:57 +08:00
500 和程序崩也一样,nginx 也是返回 502
|
21
tangMu 2023-03-06 12:29:20 +08:00
然而,代码也越来越难读了
|
22
QlanQ 2023-03-06 13:07:17 +08:00
这样写,PHP 不香吗?
要么 PHP 随便抛,要么 rust ,必须 处理 |
23
gitxuzan 2023-03-06 13:15:57 +08:00
还有你定义错误的行数都不清楚,还是老老实实写吧,到了线上不是方便了,是找麻烦
|
24
darksword21 2023-03-06 13:36:26 +08:00
我不是很理解
|
25
raynor2011 2023-03-06 16:51:42 +08:00 1
https://github.com/samber/mo 这个库更符合 lz 的想法,这是一种函数式编程的设计模式,https://en.wikipedia.org/wiki/Monad_(functional_programming)
|
26
qza1212 2023-03-06 17:13:05 +08:00
这个就是装饰器啊,不推荐在装饰器里做异常处理,这样会导致装饰器有隐藏的顺序要求
|
27
lesismal 2023-03-06 17:50:23 +08:00
转 go 这些人哪,入乡随俗了解一下,非要越搞越蹩脚。。。
|
28
securityCoding 2023-03-06 21:01:06 +08:00
你是个高手 233 ,go 代码 panic oncall 工单不得搞死你
|
29
Hanggi 2023-03-06 21:09:42 +08:00
想了解下楼主用 Go 的原因是啥,明明思想上无法接受。
就好像手里攥着圣经敲木鱼一样,怎么看都是别扭 |
30
iseki 2023-03-06 21:21:08 +08:00 via Android
Go 的整个设计都让搞 try catch 极其困难
我只会在业务逻辑里 panic 而不 recover ,以 panic 为中断整个处理的方式 |
31
SuperMild OP @Hanggi 我也很好奇,你为什么说我无法接受 Go 的语法?
if err != nil {panic(err)} 能处理错误,Must1(val, err) 也能处理错误,都符合 Go 的语法。 注意两点: 1. 看我的正文第一句话 “有些错误不需要特殊处理,就能用这些简单方便的函数”,我并没有说每一个错误都这样处理,只是有时候能偷懒,就这样偷懒,比如程序初始化阶段的一些很应该出错就崩溃的错误。 2. 我记得 Go 语言之父说过,error 就是一个普通的值,他建议大家用自己的方法写一些函数来处理这个值,怎么方便怎么来。 |
32
SuperMild OP 我不理解,上面很多人很鄙视用 panic 处理错误,意思是
A. 只要用了 panic, 就该被嘲笑,Go 语言就不该有 panic 这个函数。 B. 如果要用 panic, 就只能这样用 if err != nil {panic(err)},其他方法比如包裹一层 Must1(val, err) 就不行 究竟是 A 、B 哪个意思? |
33
CC11001100 2023-03-07 00:02:44 +08:00 1
@SuperMild 生产环境中确实应该尽量避免 panic ,太容易背锅,用户可不 care let it crash 这一套,他只知道这玩意儿不能用了就投诉,完了就得背一个 P0 故障,锅背多了就得走人了。。。
|
34
SuperMild OP @CC11001100 对呀,我也没说无脑一律 panic ,我第一句话说的就是 “有些错误不需要特殊处理,就能用这些简单方便的函数”,自己看情况用,另外我也附言给出了一个流行库,里面除了有 Must, 还有 TryOr 等多种不同的处理错误的方式,各有不同的使用场景。
|
35
dragonsunmoon 2023-03-07 00:21:25 +08:00
唉, 大道至简, go 的抽象表达能力就只能这样, 老老实实的一行代码,三行错误处理得了, 别整些其他语言的特性, 整出来的也是不伦不类.
|
36
SuperMild OP @dragonsunmoon
以前没有泛型没办法,现在原本三行错误处理可以轻松简化为一行,为什么要“老老实实”? 也没有不伦不类啊,用的都是 Go 的最最基本的语法,仅仅非常简单地包裹了一层而已,这种包裹一下变成一个方便的函数的做法,不是日常编程的常规操作吗? |
37
xuanbg 2023-03-07 02:37:43 +08:00
不要用 try catch 替代 if 来进行数据校验呀。try catch 也好,panic 也罢,这个习惯很不好的。
|
38
SuperMild OP 各位,不要执着于是否使用 panic, 重点应该是现在有了泛型,有些错误处理可以简化了,panic 只是其中一个例子而已,上面给出了 lo 和 mo 两个库,里面有 TryOr, Option 等多种方便的函数,根据需要选用。
|
39
dragonsunmoon 2023-03-07 11:01:25 +08:00
@SuperMild
探讨一些啊, 有几个问题 (1) go 官方给出的 error 处理的最佳实践是啥样的 (2) go 官方给出的泛型编程的最佳实践是啥样的 (3) 如果各个开源库都有一套自己的 error 处理方式, 那么在使用的时候会不会造成障碍, 会不会额外产生一些心智负担 |
40
SuperMild OP @dragonsunmoon 刚好我也想更详细一点说说这个问题。
上面我提到 “我记得 Go 语言之父说过,error 就是一个普通的值,他建议大家用自己的方法写一些函数来处理这个值,怎么方便怎么来” 凭着记忆,我找到了来源。 先看这篇发表在 Go 官方博客,Rob Pike 写的文章 https://go.dev/blog/errors-are-values 拉到文章最后,他总结道: > Use the language to simplify your error handling. > But remember: Whatever you do, always check your errors! 意思是,建议大家灵活使用 Go 语言去简化错误处理,只要别漏掉错误就行。 =============== 然后他推荐了一篇文章 https://jxck.hatenablog.com/entry/golang-error-handling-lesson-by-rob-pike 这篇文章是日英双语的,讲述了一个活动上,博客作者 jxck 对 Go 的错误处理有疑惑,受到 Rob Pike 指导的过程。 jxck 遇到了需要写大量 if err != nil {return err} 的情况,向 Rob Pike 请教,Rob Pike 当场就给他写了一个 Wrapper, 也就是包裹了一层,把 error 先集中记录下来,后续再一次性处理。 =============== 因此,Rob Pike 写了那篇官方博客,标题就是 Errors are values ,意思是不要把错误处理看成什么特殊的事情,error 就是一个普通的值,你如何对待别的任何数值、变量,就如何对待 error, 大胆去用常规编程技巧处理它。 |
41
SuperMild OP @dragonsunmoon 我一直很敬佩 Rob Pike
他超过 65 岁了,但他毫不墨守成规,他敢反主流。他不会问主流是什么,如果大家不符合主流会不会沟通困难,他设计的 Go 语言就极大胆地反主流,一个新语言,静态类型的,敢没有 try-catch 处理异常,没有泛型,敢加进指针,没有标准的面向对象,而是用隐性接口,这一大堆设计都是非常大胆的。 按照上面很多人的说法,完全可以说 Go 语言本身就有一大堆不伦不类的设计。但是,为什么要这样想问题呢,连 60 多岁的老人都敢勇于“标新立异”。 ============ 题外话,Go 官方网站的文档 pkg.go.dev 是当今极罕见,代码不带语法高亮的,但是我们也许并未感觉有啥特别不方便。因为 Rob Pike 发现,语法高亮其实没啥用。 我自己的体验是,写代码时语法高亮有点帮助,但阅读代码时,一旦沉浸进去,是绝对感受不到有没有高亮的区别的。 |
42
fds 2023-03-07 13:52:39 +08:00
op 推荐的 https://github.com/samber/do 这个 DI 库看起来不错,找机会试用下,少写点儿全局变量。
|
43
standchan 2023-03-16 10:21:44 +08:00
panic 没啥问题,但是一般我们都是在程序初始化的过程中如果发生问题就直接 panic 掉,比如数据目录的创建失败之类的,在程序运行过程中是极少 panic 的(几乎没有)你写这个用起来舒服,但是 log 报错的代码行数都是 Try 函数的第三行吧,这个就很麻烦。
|
45
SuperMild OP @standchan 你看我正文第一句话 “有些错误不需要特殊处理”,如果我没想过这个函数的使用场景有限,我又怎么会说这句话呢。
|
46
libinglong9 326 天前 via iPhone
还是用 nodejs 吧
|