网络异常,图片无法展示
|
关键字介绍
panic
:一旦出现,就意味着程序的结束并退出。Go 语言中panic
关键字主要用于主动抛出异常,类似java
等语言中的throw
关键字。recover
:将程序状态从严重的错误中恢复到正常状态。Go 语言中recover
关键字主要用于捕获异常,让程序回到正常状态,类似java
等语言中的try ... catch
。
使用
panic
- 发生
panic
后,后续代码不会执行 - 发生
panic
后,会执行defer
链表
- 我们先创建两个协程,然后在其中一个协程里发生
panic
。看看另一个协程会怎么样。
package main import "fmt" func main() { // 第一个协程 go func() { var i int for { i++ fmt.Println("协程1") time.Sleep(1*time.Second) // 3秒后发生panic if i==3 { panic("异常退出") } } }() // 第二个协程 go func() { for { fmt.Println("协程2") time.Sleep(1*time.Second) } }() // 让主协程不退出 for { time.Sleep(1*time.Second) } }
- 当程序执行5秒后,其中一个协程就会发生
panic("异常退出")
,这时程序就会退出,随之另一个协程也结束了。
输出:
协程2 协程1 协程2 协程1 协程2 协程1 协程2 panic: 异常退出 goroutine 6 [running]: main.main.func1() /home/zheng/STUDY/GoWork/demo/main.go:28 +0xb9 created by main.main /home/zheng/STUDY/GoWork/demo/main.go:15 +0x35
- 所以
panic
如果不捕获,就会导致程序整体关闭的严重的后果 recovery
- 为了解决
panic
的问题,go
也提供了recovery
这个函数,用于捕获异常,保证程序能正常运行。 - 只对当前
goroutine
发生的panic
有效 recovery
要配合defer
使用,因为recovery
要在发生panic
后执行才有效,但是发生panic
的后续代码不会执行了,但是会执行defer
- 我们对上面程序的第一个协程加上
recovery
// 第一个协程 go func() { // 捕获异常 defer func() { err:=recover() fmt.Printf("捕获的:%s\n",err) }() var i int for { i++ fmt.Println("协程1") time.Sleep(1*time.Second) // 3秒后发生panic if i==3 { panic("异常退出") } } }()
- 输出:
协程2 协程1 协程1 协程2 协程2 协程1 协程2 捕获的:异常退出 协程2 协程2 ...
- 可以看到线程1的
recovery
捕获当前协程的panic
的异常,并输出异常原因。但是另一个协程2还会继续执行。