recover注意事项
2023/8/27大约 1 分钟
defer结合recover通常用于捕获panic
正确使用示例
func PrintRecover() {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println(err)
		}
	}()
	fmt.Println("a")
	panic("some thing")
	fmt.Println("b")
}使用示例
func ExamplePrintRecover() {
	PrintRecover()
	// Output:
	// a
	// some thing
}错误用例:不使用defer
func FailRecoverWithoutDefer() {
	if err := recover(); err != nil {
		fmt.Println(err)
	}
	fmt.Println("a")
	panic("some thing")
	fmt.Println("b")
}警告
不使用defer 方式,将无法捕获异常,程序陷入panic
错误用例:recover 在 defer 嵌套函数中
func FailRecoverWithoutLevelDefer() {
	defer func() {
		func() { //recover 在 defer 嵌套函数中
			if err := recover(); err != nil {
				fmt.Println(err)
			}
		}()
	}()
	fmt.Println("a")
	panic("some thing")
	fmt.Println("b")
}警告
defer recover和panic不在同一层级,导致无法捕获异常,程序陷入panic
defer recover 再次panic
package main
import "fmt"
func main() {
	defer func() {
		fmt.Println("xx", recover())
	}()
	defer func() {
		defer func() {
			fmt.Println("yy", recover())
		}()
		panic(1)
	}()
	defer recover()
	panic(2)
}执行结果
yy 1
xx 2其中:
- defer recover(),由于不是在一个匿名函数中,所以无法捕获到panic,导致panic继续向上抛出,被外层- recover捕获到。
- panic(1)会替换- panic(2)直至被捕获处理。
package main
import "fmt"
func main() {
	defer func() {
		fmt.Println("xx", recover())
	}()
	defer func() {
		defer fmt.Println("yy", recover())
		panic(1)
	}()
	defer recover()
	panic(2)
}执行结果
yy 2
xx 1