> For the complete documentation index, see [llms.txt](https://hantmac.gitbook.io/mastering-go-second/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hantmac.gitbook.io/mastering-go-second/02.0/02.6.md).

# Panic 和 Recover

本节将向你介绍上一章中首先提到的技巧。该技术涉及`panic()`和`recover()`函数的使用，将在`panicRecover.go`中进行介绍，同样分为三部分。

第一段代码：

```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()`函数的实现。函数`a()`的最重要部分是延迟代码块，该代码块实现了一个匿名函数，当调用`panic()`时将调用该匿名函数。

第二段代码：

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

最后一段代码：

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

执行`panicRecover.go`产生如下输出：

```
$ 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`程序会按我们的意愿结束而不会发生崩溃，因为在`defer`中使用的匿名函数控制了异常情况。还要注意，函数`b()`对函数`a()`一无所知；但是，函数 `a()`包含处理函数`b()`异常情况的 Go 代码。
