go语言学习笔记——panic和recover

panic

panic通常是不可以恢复的错误程序

panic 抛出异常的时候,会把程序的堆栈信息打印出来。

程序执行到panic的时候,是不会继续向下执行的。

使用panic的调用程序,是不会阻止defer程序的执行的:

func TestPanic(t *testing.T) {
	defer func() {
		fmt.Println("finally")
	}()
	fmt.Println("start")
	panic(errors.New("Something wrong"))
}
复制代码

程序输出

=== RUN   TestPanic
start
finally
--- FAIL: TestPanic (0.00s)
panic: Something wrong [recovered]
	panic: Something wrong

goroutine 6 [running]:
testing.tRunner.func1.2({0x975600, 0xc000042530})
	D:/Go/src/testing/testing.go:1209 +0x24e
testing.tRunner.func1()
	D:/Go/src/testing/testing.go:1212 +0x218
panic({0x975600, 0xc000042530})
	D:/Go/src/runtime/panic.go:1038 +0x215
command-line-arguments.TestPanic(0x0)
复制代码

os.Exit() 推出程序,是不会运行defer的具体函数的

func TestPanic(t *testing.T) {
	defer func() {
		fmt.Println("finally")
	}()
	fmt.Println("start")
	os.Exit(1)
	//panic(errors.New("Something wrong"))
}
复制代码

输出

=== RUN   TestPanic
start
复制代码

recover

recover主要是防止代码执行panic的时候,导致进程崩溃,使用recover,可以让进程依旧继续运行

func TestRecover(t *testing.T) {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println("Catch Error", err)
		}
	}()
	fmt.Println("start")
	panic(errors.New("this error"))
}
复制代码

输出结果

=== RUN   TestRecover
start
Catch Error this error
--- PASS: TestRecover (0.00s)
PASS
复制代码

这里虽然执行了panic的函数,但是执行panic之后,在defer里面,又继续调用了recover进行异常的捕捉,这种实现方式,有点像php或java里面的try {} catch() {}的逻辑

但是recover方式也不建议盲目使用:

假如服务器的没有对应的应用资源,导致执行panic,进行异常抛出,但是又再次使用recover进行恢复,一些health check的程序,只是check了一下进程是否存在。就会导致所谓的僵尸进程:进程还在,但是没有资源执行对应的逻辑。

所以使用recover的时候,还是需要经过一些思考的,不能盲目的使用。

猜你喜欢

转载自juejin.im/post/7042933128947728392