宕机恢复(recover)——防止程序崩溃
# 3. 宕机恢复(recover)——防止程序崩溃
# 介绍
Recover 是一个Go语言的内建函数,可以让进入宕机流程中的 goroutine 恢复过来,recover 仅在延迟函数 defer 中有效,在正常的执行过程中,调用 recover 会返回 nil 并且没有其他任何效果,如果当前的 goroutine 陷入恐慌,调用 recover 可以捕获到 panic 的输入值,并且恢复正常的执行。
通常来说,不应该对进入 panic 宕机的程序做任何处理,但有时,需要我们可以从宕机中恢复,至少我们可以在程序崩溃前,做一些操作,举个例子,当 web 服务器遇到不可预料的严重问题时,在崩溃前应该将所有的连接关闭,如果不做任何处理,会使得客户端一直处于等待状态,如果 web 服务器还在开发阶段,服务器甚至可以将异常信息反馈到客户端,帮助调试。
# 提示
在其他语言里,宕机往往以异常的形式存在,底层抛出异常,上层逻辑通过 try/catch 机制捕获异常,没有被捕获的严重异常会导致宕机,捕获的异常可以被忽略,让代码继续运行。
Go语言没有异常系统,其使用 panic 触发宕机类似于其他语言的抛出异常,recover 的宕机恢复机制就对应其他语言中的 try/catch 机制。
# 让程序在崩溃时继续执行(引入机制:defer+recover机制处理错误)
package main
import "fmt"
func main() {
testRecover(10, 0)
fmt.Println("成功执行后面语句")
}
func testRecover(a int, b int) int {
// 利用defer+recover来捕获异常(defer后加上匿名函数的调用)
defer func() {
// 调用内置的recover来捕获错误
err := recover() // 没有捕获到异常错误,返回nil
if err != nil {
fmt.Println("捕获异常信息", err)
//errors.New(err)
}
}()
return a / b
}
/*
捕获异常信息 runtime error: integer divide by zero
成功执行后面语句
*/
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
# panic 和 recover 的关系
panic 和 recover 的组合有如下特性:
有 panic 没 recover,程序宕机。
有 panic 也有 recover,程序不会宕机,执行完对应的 defer 后,从宕机点退出当前函数后继续执行。
# 提示
虽然 panic/recover 能模拟其他语言的异常机制,但并不建议在编写普通函数时也经常性使用这种特性。
在 panic 触发的 defer 函数内,可以继续调用 panic,进一步将错误外抛,直到程序整体崩溃。
如果想在捕获错误时设置当前函数的返回值,可以对返回值使用命名返回值方式直接进行设置。