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 的函数中生效