无论是代码运行错误由 Runtime 层抛出的 panic 崩溃,还是主动触发的 panic 崩溃,都可以配合 defer 和 recover 实现错误捕捉和恢复,让代码在发生崩溃后允许继续运行。

Go 没有异常系统,其使用 panic 触发宕机类似于其他语言的抛出异常,那么 recover 的宕机恢复机制就对应 try/catch 机制。

让程序在崩溃时继续执行

下面的代码实现了 ProtectRun() 函数,该函数传入一个匿名函数或闭包后的执行函数,当传入函数以任何形式发生 panic 崩溃后,可以将崩溃发生的错误打印出来,同时允许后面的代码继续运行,不会造成整个进程的崩溃。

保护运行函数:

package main import ("fmt""runtime") // 崩溃时需要传递的上下文信息type panicContext struct {function string // 所在函数} // 保护方式允许一个函数func ProtectRun(entry func()) { // 延迟处理的函数defer func() { // 发生宕机时,获取panic传递的上下文并打印err := recover() switch err.(type) {case runtime.Error: // 运行时错误fmt.Println("runtime error:", err)default: // 非运行时错误fmt.Println("error:", err)} }() entry() } func main() {fmt.Println("运行前") // 允许一段手动触发的错误ProtectRun(func() { fmt.Println("手动宕机前") // 使用panic传递上下文panic(&panicContext{"手动触发panic",}) fmt.Println("手动宕机后")}) // 故意造成空指针访问错误ProtectRun(func() { fmt.Println("赋值宕机前") var a *int*a = 1 fmt.Println("赋值宕机后")}) fmt.Println("运行后")}

对代码的说明:

第 9 行声明描述错误的结构体,成员保存错误的执行函数。

第 17 行使用 defer 将闭包延迟执行,当 panic 触发崩溃时,ProtectRun() 函数将结束运行,此时 defer 后的闭包将会发生调用。

第 20 行,recover() 获取到 panic 传入的参数。

第 22 行,使用 switch 对 err 变量进行类型断言。

第 23 行,如果错误是有 Runtime 层抛出的运行时错误,如空指针访问、除数为 0 等情况,打印运行时错误。

第 25 行,其他错误,打印传递过来的错误数据。

第 44 行,使用 panic 手动触发一个错误,并将一个结构体附带信息传递过去,此时,recover 就会获取到这个结构体信息,并打印出来。

第 57 行,模拟代码中空指针赋值造成的错误,此时会由 Runtime 层抛出错误,被 ProtectRun() 函数的 recover() 函数捕获到。

panic和recover的关系

panic 和 defer 的组合有如下特性:

有 panic 没 recover,程序宕机。

有 panic 也有 recover 捕获,程序不会宕机。执行完对应的 defer 后,从宕机点退出当前函数后继续执行。

更多golang知识请关注PHP中文网golang教程栏目。

更多相关文章

  1. go语言中一种常见的错误
  2. golang如何调用函数?
  3. 记一次因为共享变量的犯错误
  4. 详解Golang中函数作为值与类型
  5. go语言中普通函数与方法的区别是什么?
  6. 详解Go 中方法与函数的区别
  7. 关于golang封装一个bash函数,用于执行bash命令
  8. 总结Golang实现PHP常用函数
  9. FusionCharts 2D柱状图和折线图的组合图调试错误

随机推荐

  1. android wifi调试(无线调试) 一步到位
  2. Android:如何自动刷新UI上的元素(无需刷新
  3. 单例模式----设计模式系列
  4. android4.0.4 系统默认值的修改
  5. 添加/修改子项的Firebase通知
  6. android MPChart图标使用详解
  7. 如何在 android 中转换为 'file:///stora
  8. Android SDK更新以及ADT更新出现问题的解
  9. Ubuntu Android/Sdk/build-tools/23.0.3/
  10. 如何执行删除请求而不返回类型或回调?(改