> For the complete documentation index, see [llms.txt](https://wskdsgcf.gitbook.io/mastering-go-zh-cn/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://wskdsgcf.gitbook.io/mastering-go-zh-cn/2-go-nei-bu-ji-zhi/02.7.md).

# 02.7 Panic和Recover

​ 本节将向您介绍第1章“Go和操作系统”中首次提到的技术。这种技术涉及使用`panic()`和`recover()`函数，代码在`panicRecover.go`中，将分三部分进行讨论。

​ 严格来说，`panic()`是一个内置的Go函数，它终止Go程序的当前流程并开始`panicking`！ 另一方面，`recover()`函数也是一个内置的Go函数，允许你收回那些使用了`panic()`函数的`goroutine`的控制权。

第一部分的程序如下：

> ```go
> package main
> import (
>     "fmt"
> )
> func a() {
>     fmt.Println("Inside a()")
>     defer func() {
>         if c := recover(); c != nil {
>             fmt.Println("Recover inside a()!")
>            }
>     }()
>     fmt.Println("About to call b()")
>     b()
>     fmt.Println("b() exited!")
>     fmt.Println("Exiting a()")
> }
> ```

除了import语句块，这部分代码实现了一个函数`a()`，这个函数最重要的部分是`defer`代码块，它实现了一个匿名函数，当`panic()`函数被调用的时候，这个匿名函数就会被调用。

第二部分的代码：

> ```go
> func b() {
>     fmt.Println("Inside b()")
>     panic("Panic in b()!")
>     fmt.Println("Exiting b()")
> }
> ```

最后一部分代码解释了`panic()`和`recover()`函数：

> ```go
> func main() {
>     a()
>     fmt.Println("main() ended!")
> }
> ```

执行完整的代码，会得到如下的输出：

> ```
> $ go run panicRecover.go
> Inside a()
> About to call b()
> Inside b()
> Recover inside a()!
> main() ended!
> ```

这里发生的事真的令人印象深刻！ 但是，正如您从输出中看到的那样，`a`函数没有正常结束，因为它的最后两个语句没有执行：

> ```go
> fmt.Println("b() exited!")
> fmt.Println("Exiting a()")
> ```

然而，好消息是`panicRecover.go`根据我们的意愿结束而没有`panicking`，因为`defer`中使用的匿名函数控制了局面！ 另请注意，函数`b`对函数`a`一无所知。 但是，函数`a`包含处理`b`函数的panic情况的Go代码！
