异常处理

异常处理 #

概述 #

  • Go 没有 try..catch 这种异常机制,而是使用 panicrecover
  • panic 在任何地方都可以执行,recover 只有在 defer 调用的函数中才有效。

defer #

  • defer 用于定义在函数执行结束后执行的语句
  • 多个 defer 会形成 defer 栈,后定义的 defer 语句会被最先调用
  • 即使函数发生严重错误也会执行
  • 通过与匿名函数配合可以在 return 之后修改结果

定义多个 defer #

func testDefer() {
	fmt.Println("a")
	defer fmt.Println("b")
	defer fmt.Println("c")
	defer func() {
		fmt.Println("d")
	}()
}
testDefer() //a d c b

改变返回值 #

由于 defer 在函数执行结束后执行,所以可以用于改变命名返回值的值

错误的用法

func changeResult(x int) int {
	defer func() {
		x++	//返回的值,改变变量没有用
	}()
	return x
}
x = changeResult(8)
fmt.Println("x", x) //x 8

正确的用法

func changeResult2(x int) (result int) {
	defer func() {
		result++
	}()
	return x
}
x = changeResult2(8)
fmt.Println("x", x) //x 9

panic 与 recover #

  • panic 用于向上传递异常,执行在 defer 之后,表示非常严重不可恢复的异常,会导致程序挂掉
  • recover 可以对 panic 进行捕获,使 panic 停止向上传递

使用 panic #

func one() { fmt.Println("func one") }
func two() { fmt.Println("func two") }
func broken() {
	one()
	panic("func broken with Panic")
	two()
}
broken()

输出

func one
panic: func broken with Panic
异常消息...程序中断

使用 recover #

func one() { fmt.Println("func one") }
func two() { fmt.Println("func two") }
func catch() {
	one()
	defer func() {
		if err := recover(); err != nil {
			fmt.Println("func catch with Recover")
		}
	}()
	panic("func broken with Panic")
	two()
}
catch()

输出

func one
func catch with Recover

注意

  • defer 需要放在 panic 之前定义
  • recover 之后,逻辑并不会恢复到 panic 那个点去,函数还是会在 defer 之后返回
沪ICP备17055033号-2