Panic 和 Recover

本节将向你介绍上一章中首先提到的技巧。该技术涉及panic()recover()函数的使用,将在panicRecover.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()时将调用该匿名函数。

第二段代码:

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

最后一段代码:

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()函数没有正常结束,它的最后两个语句没有得到执行:

fmt.Println("b() exited!")
fmt.Println("Exiting a()")

不过,好在panicRecover.go程序会按我们的意愿结束而不会发生崩溃,因为在defer中使用的匿名函数控制了异常情况。还要注意,函数b()对函数a()一无所知;但是,函数 a()包含处理函数b()异常情况的 Go 代码。

Last updated