Go中的panic与recover机制

panic

Go的类型系统会在编译时捕获很多错误,但有些错误只能在运行时检查,如数组访问越界、空指针引用等。这些运行时错误会引起 painc 异常。一般而言,当 panic 发生时,程序会中断执行,并立即执行在该 goroutine 中被延迟的函数。随后,程序崩溃并输出日志信息,日志信息包括 panic value 和函数调用的堆栈跟踪信息。
我们也可以手动调用内置的 panic 函数去触发 panic 异常,panic 函数可接受任何值作为参数,如
panic(fmt.Sprintf("Invalid message %s", msg))
由于 panic 会引起程序的崩溃,因此 panic 一般用于严重错误,如程序内部的逻辑不一致。对于大部分漏洞,我们应该使用Go提供的错误机制,而不是panic,尽量避免程序的崩溃。在健壮的程序中,任何可以预料到的错误,如不正确的输入、错误的配置或是失败的I/O操作都应该被优雅的处理,最好的处理方式,就是使用Go的错误机制。
注意:在Go的 panic 机制中,延迟函数的调用在释放堆栈信息之前。

recover

通常来说,不应该对panic异常做任何处理,但有时,也许我们可以从异常中恢复,至少我们可以在程序崩溃前,做一些操作。举个例子,当web服务器遇到不可预料的严重问题时,在崩溃前应该将所有的连接关闭;如果不做任何处理,会使得客户端一直处于等待状态。如果web服务器还在开发阶段,服务器甚至可以将异常信息反馈到客户端,帮助调试。
如果在deferred函数中调用了内置函数recover,并且定义该defer语句的函数发生了panic异常,recover会使程序从panic中恢复,并返回panic value。导致panic异常的函数不会继续运行,但能正常返回。在未发生panic时调用recover,recover会返回nil。
例如:

func Parse(input string) (s *syntax, err error) {
     defer func() {
        if p := recover(); p != nil {
            err = fmt.Errorf("internal error: %v", p)
        }
    }()
}

有些情况下,我们无法恢复。某些致命错误会导致Go在运行时终止程序,如内存不足。

你可能感兴趣的:(Go中的panic与recover机制)