单线程
主线程里没有其他方法调用时发生 panic,有 recover 则处理,没有则不处理,主线程结束,panic 后续不执行;
func main() {
defer func() {
if err := recover(); err != nil {
fmt.Println("main panic:", err)
}
}()
panic("main panic")
fmt.Println("main end")
}
//
main panic: main panic
主线程里有其他方法调用时,子方法发生 panic,子方法和主方法都不 recover,主线程结束,后续不执行;
func main() {
test()
fmt.Println("main end")
}
func test() {
panic("test panic")
}
//
panic: test panic
goroutine 1 [running]:
main.test(...)
E:/dubinyang1993/go-demo/defer/main.go:13
main.main()
E:/dubinyang1993/go-demo/defer/main.go:8 +0x27
子方法发生 panic,子方法不 recover,主方法 recover,主线程结束,后续不执行;
func main() {
defer func() {
if r := recover(); r != nil {
fmt.Println("main panic:", r)
}
}()
test()
fmt.Println("main end")
}
func test() {
panic("test panic")
}
//
main panic: test panic
子方法发生 panic,子方法 recover,主方法有无 recover 没有影响,主线程继续执行;
func main() {
defer func() {
if r := recover(); r != nil {
fmt.Println("main panic:", r)
}
}()
test()
fmt.Println("main end")
}
func test() {
defer func() {
if r := recover(); r != nil {
fmt.Println("test panic:", r)
}
}()
panic("test panic")
}
//
test panic: test panic
main end
多线程
子线程的 panic 是无法被主线程的 recover 接收处理的,如果子线程本身不进行 recover,主线程结束,后续不执行;
func main() {
defer func() {
if r := recover(); r != nil {
fmt.Println("main panic:", r)
}
}()
go test()
time.Sleep(5 * time.Second)
fmt.Println("main end")
}
func test() {
panic("test panic")
}
//
panic: test panic
goroutine 6 [running]:
main.test()
E:/dubinyang1993/go-demo/defer/main.go:22 +0x27
created by main.main
E:/dubinyang1993/go-demo/defer/main.go:15 +0x46
如果子线程本身进行了 recover,主线程继续执行;
func main() {
go test()
time.Sleep(5 * time.Second)
fmt.Println("main end")
}
func test() {
defer func() {
if r := recover(); r != nil {
fmt.Println("test panic:", r)
}
}()
panic("test panic")
}
//
test panic: test panic
main end
总结:一般情况下单线程直接在主方法入口处加 recover 即可,多线程时需要在每个子线程方法里都加上 recover.