1.panic
在goroutine当中一旦触发panic(宕机),将从
panic处终止程序进行,同时调用该panic调用栈上的所有defer,执行defer中若无recover,则exit异常退出
package main
import "fmt"
func main() {
fmt.Println("main start")
go test()
fmt.Println("main end")
}
func test() {
defer fmt.Println("test")
panic("test panic")
}
2.recover
在panic调用栈defer,若调用panic(包括主动和被动)的函数栈上有recover,则截获该panic,程序继续从panic处执行,运行完毕后,exit正常退出,否则exit异常退出
package main
import (
"fmt"
)
func main() {
go test()
}
func test() {
defer func() {
if r := recover(); r != nil {
fmt.Println("recovery")
}
}()
panic("test panic")
}
3.注意事项
- 对于go1.6以上版本,如果出现 并发map读写 程序会直接以 fatal error 崩溃,即使在同一个协程内有recover()也不能恢复
- 对于panic显示的函数堆栈调用关系,debug.PrintStack()也可以做到
- 一般来说,不建议在业务代码中使用 panic
- 如果当前 goroutine 中所有 deferred 函数都不包含 recover 就会造成整个程序崩溃
- 当程序启动阶段发生不可逆转的错误时,可以在 init 或 main 函数中使用 panic
4.总结
panic 用于真正异常的情况
error 尽可能提供简明的上下文信息,方便定位问题
recover 生效范围,在当前 goroutine 的被 defer 的函数中生效