不捕获 error
典型的像如下代码:
func getBar()(*bar, err){
//some errors
if err := hasError(); err != nil{
return nil, err
}
//do sth
return new(bar), nil
}
func foo(){
b, _ := getBar()
b.DoSth() //panic
}
以下典型的 golang 代码看起来很烦,而且直接影响代码风格美观程度。
func getBar()(*bar, err){
//do sth
return 0, nil
}
func foo()error{
if b1, err := getBar(); err != nil{
return err
}
if b2, err := getBar(); err != nil{
return err
}
return nil
}
我在很多项目里看到新手或者从其他语言转过来的同学,喜欢写 if p, _ := getBar()
这样的代码,然后继续处理接下来的流程。这样做的问题在于你直接忽略掉了你所调用代码产生的错误,你内心默认的代码运行方式是:“我的代码一定会以正确的方式运行。”
在很多其他的语言里会有 try catch 这样的机制,可以让你在函数调用的外部直接捕获异常。当随之带来的问题是 try catch 是跨函数跨模块和函数的,容易出现抛出的异常被并不适合这个模块的代码模块去处理。
go 语言这个错误处理方式虽然丑陋,但简单有效。它这样做简单的让你把 error 直接丢给上一层,上一层可以决定这个错误是继续传递还是中止处理。当我把写 go 关于错误处理的思维方式转变成:不放过任何一个错误后,写代码的心智负担将得极低。我只需要关心当前的函数输入输出数据是否合法,以及调用其他函数时出错后选择继续还是中止。而且 go 语言这种小粒度的 error 处理方式几乎不用 care 错误的类型,遇到不合法 /异常 /错误 /非正常流程后只需要 error 继续 /中止一把梭即可。
不信你可以看看下面是如何用简单的错误处理是如何改掉 HTTP 200 一把梭的毛病。
func Query(w http.ResponseWriter, r *http.Request) {
var data RequestData
err := json.NewDecoder(r.Body).Decode(&data)
if err != nil{
w.WriteHeader( http.StatusBadRequest)
return
}
if data.Name == "not existed"{
w.WriteHeader( http.StatusNotFound)
return
}
w.WriteHeader( http.StatusOK)
return
}
某些 golang 的 web framework 会调用 recover 方法,以防止 HTTP server 崩溃。不得不说这是它提供的一种“助纣为虐”的方式让你去忽略掉某些致命的错误。这完全没必要,守护进程比 recover 要靠谱得多(还能自动获得重启大法的加成:) )。我个人认为在代码里面尽量不要调用任何 recover 的代码,尽量在代码部署到生产环境前测试发现所有可能的 panic 错误并修复掉。如果代码发生 panic 问题,肯定是有什么地方你没有想到或没设计好,你需要做的是修改代码而不是掩盖错误。
捕获所有错误你唯一需要付出的代价就是:多敲几个字。而付出的这点代价你将获得:底层成本的设计负担,无脑的心智负担,健壮的代码,严格的输入输出限定。
1
kalista 2022-07-22 22:11:17 +08:00
用不用 recover 还是得看场景,对于开发来说,当然希望 panic 被我们感知到比较好,但是有些 to B 产品,甲方是会关注你是否有 panic 的,对于这种,我们需要做到既不 panic (不被甲方知道)同时我们又能知道服务出现过问题,总之就是具体事情具体分析。永远不能脱离业务
|
2
lysS 2022-07-22 22:15:13 +08:00
我是这样安慰自己的:总比 C 返回一个 err code 好吧。。。。
|
3
Ricardo5 2022-07-22 23:34:07 +08:00 via Android
主要还是太丑了,rust 用模式匹配看起来就美观很多
|
4
messyidea 2022-07-23 05:22:17 +08:00 via Android 2
panic 了整个进程就退出了,web framework 的所有其它并发请求都会失败,而如果 recover ,则不会影响其它并发请求。再说发现程序是否有 panic ,不一定要进程退出,panic 打点 metrics 告警也能发现问题
|
5
Aloento 2022-07-23 06:10:43 +08:00
总之就是太丑而且说真的麻烦,错误处理还得看 C#(你甚至都不知道它到底会不会报错)
|
7
tqyq88 2022-07-23 08:16:07 +08:00
判断 err != nil 才是恶心的根源
|
8
lidage 2022-07-23 15:18:39 +08:00 via iPhone
你捕获了又能怎么样呢,你能写出绝对完美的程序?自欺欺人,不如直接忽略掉,在重要的地方捕获 err 或者打日志,只有妥协,才能走的更快
|
9
mmdsun 2022-07-24 01:15:22 +08:00 via iPhone
@dcoder 可能说的是 C#异常不像 Java 那样必须 try catch 捕获,不然编译不过? 反正 Java 检查性异常满屏的 try catch ,看起来也十分不雅,我会用 lombok 插件来处理这种情况。
|
10
Aloento 2022-07-24 01:18:30 +08:00
|
12
buffzty 2022-07-24 12:46:37 +08:00
绝大多数觉得 go 语言错误处理不好的都是菜逼. 因为 go 的错误处理跟 c 语言是一样的,而且比 c 语言好.
并且 go 是有 try catch 模式的(不是 recover 那种) 每次看见一群菜鸟喷 err 错误处理就想笑 咋没人喷 c 的错误处理? |