在Go中,标准方法是通过返回值error来处理错误。这允许在每个点显式控制在发生错误时该怎么办。Panic是处理不可预见的灾难性情况的机制:它会中断执行直到最近的defer,在那里可以使用recover进行“救援”。但是recover仅在defer内部工作。
最佳实践:
func safeDivide(a, b int) (int, error) { if b == 0 { return 0, errors.New("divide by zero") } return a/b, nil } func mustDivide(a, b int) int { if b == 0 { panic("divide by zero!") } return a/b }
是否可以在程序的任何地方通过recover“捕获”任何panic错误?
答案: 不可以,recover只会在defer内部和调用panic的同一个goroutine中有效。在其他情况下,panic会终止该(或所有)goroutine的执行——这常常会出乎意料。
故事
在REST API中,使用panic处理业务逻辑中的普通错误。这导致了应用程序的明显崩溃和不正确的日志,因为recover并不总是正确触发。
故事
在支付处理服务中,主要函数中实现了defer + recover以“捕获”所有panic,但忘记了goroutine——在子goroutine中没有defer/recover,应用程序崩溃并产生“可怕”的错误,导致部分交易处于不一致状态。
故事
在复杂结构的解析器中忘记返回错误,改为使用panic——这使得维护和测试变得复杂,最终不得不完全重写错误处理,以便进行详细的日志记录和正确的用户体验。