Go从入门到精通——函数——宕机恢复(recover)——防止程序崩溃
宕机恢复(recover)——防止程序崩溃
无论是代码运行错误由 Runtime 层抛出的 panic 崩溃,还是主动触发的 panic 崩溃,都可以配合 defer 和 recover 实现错误捕捉和恢复,让代码在发生崩溃后允许继续运行。
1 2 | 提示: 在其他语言里,宕机往往以一场的形式存在,底层抛出一场,上层逻辑通过 try/catch 机制捕获异常,没有被捕获的严重异常会导致宕机,捕获的异常可以被忽略,让代码继续运行。 Go 没有异常系统,其使用 panic 触发宕机类似于其他语言的抛出异常,那么 recover 的宕机恢复机制就对应 try/catch 机制。 |
一、让程序在崩溃时继续执行
下面的代码实现了 PrtectRun() 函数,该函数传入一个匿名函数或闭包后的执行函数,当传入函数以任何形式发生 panic 崩溃后,可以将崩溃发生的错误打印出来,同时允许后面的代码继续运行,不会造成整个进程的崩溃。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | package main import ( "fmt" "runtime" ) //声明描述错误的结构体,成员保存错误的执行函数。 //崩溃时需要传递的上下文信息 type panicContext struct { function string } //保护方式允许一个函数 func ProtectRun(entry func ()) { //延迟处理的函数。使用defer将闭包延迟执行, //当 panic 触发崩溃时,ProtectRun()函数将结束运行,此时 defer 后的闭包将会发生调用。 defer func () { //发生宕机时,recover() 获取 panic 传递的上下文并打印 err := recover() switch err.( type ) { //如果错误是runtime层抛出的运行时从无哦,如空指针访问、除数为0等情况,打印运行时错误。 case runtime.Error: fmt.Println( "runtime error:" , err) default : fmt.Println( "error:" , err) } }() entry() } func main() { fmt.Println( "运行前" ) //允许一段手动触发的错误 ProtectRun( func () { fmt.Println( "手动宕机前" ) //使用 panic 传递上下问。使用 panic 手动触发一个错误,并将一个结构体附带信息传递过去, //此时,recover 就会获取到这个结构体信息,并打印出来。 panic(&panicContext{ "手动触发panic" }) fmt.Println( "手动宕机后" ) }) //故意造成空指针访问错误 ProtectRun( func () { fmt.Println( "赋值宕机前" ) var a *int //模拟代码中空指针赋值造成的错误,此时会由 Runtime 层抛出错误,被 ProtectRun() 函数的 recover() 函数捕获到。 *a = 1 fmt.Println( "赋值宕机后" ) }) fmt.Println( "运行后" ) } |
代码输出如下:
1 2 3 4 5 6 7 8 9 10 | Starting: D:\ go -testfiles\bin\dlv.exe dap --check- go -version=false --listen=127.0.0.1:54313 from d:\ go -testfiles DAP server listening at: 127.0.0.1:54313 Type 'dlv help' for list of commands. 运行前 手动宕机前 error: &{手动触发panic} 赋值宕机前 runtime error: runtime error: invalid memory address or nil pointer dereference 运行后 Process 15388 has exited with status 0 |
二、panic 和 recover 的关系
panic 和 defer 的组合有如下几个特性。
- 有 panic 没 recover,程序宕机。
- 有 panic 也有 recover 捕获,程序不会宕机。执行完对应的 defer 后,从宕机点退出当前函数后继续执行。
分类:
Go专题精讲
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具