go编译需慎用panic,这种情况会捕获失败

56 阅读2分钟

这是一句很激进的话,请不要使用 panic() 。

不要以为可以使用 recover() 来捕获恢复就没事了,一不小心就会闹出麻烦。

我们来看看下面这段代码,它演示了使用 recover() 捕获panic() 失败的场景

运行这段代码,依旧会抛出警告

这是因为,抛出警告的代码是在一个新的 goroutine 中发生的,通过 go panicFunc运行。而只有panic触发和调用recover在同一个goroutine 中时,recover才能捕获成功。

所以这个程序依然还会崩溃,这确实太糟糕了。

并且,会使程序崩溃并不是唯一让你拒绝使用recover的原因,还有其他的因素:

  • 在生产环境中,代码必须具备极高的稳健性 程序意外崩溃是绝对要避免的,因为它会导致系统宕机,从而影响用户体验,并可能对您的企业声誉造成不利影响。

  • 系统中某一部分的panic可能会引发连锁反应 这可能导致系统(尤其是在微服务或者分布式系统)中其他部分接连出现故障(可能是级联失败)。

应把panic的代码修改成err错误返回,比如:

修改后的代码为:

程序在根据错误进行相应的处理,比如:

  • 重试操作

  • 使用默认值

  • 记录详细的调试信息

  • 程序终止

  • 其他...

灵活处理错误对于构建一个稳定的系统至关重要。

而 panic 只能作为最后手段:

  • 仅在遇到真正无法恢复的错误时才使用panic,即如果继续运行程序可能会引发更严重的问题,比如数据损坏或未知行为。

  • 在程序初始化阶段,如果一个关键组件启动失败,panic或许是“可接受的”,因为它表明程序无法按预期运行。