go语言学习笔记 — 基础 — 函数(12):防止程序崩溃—— 宕机恢复(recover)
Posted Locutus
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了go语言学习笔记 — 基础 — 函数(12):防止程序崩溃—— 宕机恢复(recover)相关的知识,希望对你有一定的参考价值。
无论是代码运行错误由Runtime层抛出的panic崩溃(如空指针访问,除数为0等情况),还是主动触发的panic崩溃,都可以使用defer和recover实现错误捕捉和恢复,使代码在崩溃后继续运行。
go语言没有异常系统,使用panic触发宕机类似其他语言的抛出异常,那么recover宕机恢复机制就对应try/catch捕获异常机制。
1. 让程序在崩溃时继续执行
下面代码实现函数保护作用,该函数传入一个匿名函数,当传入函数以任何形式发生panic崩溃时,可以把崩溃错误打印出来,同时允许代码继续执行,不会使整个进程崩溃。
package func_test
import (
"fmt"
"runtime"
"testing"
)
// 声明描述错误的结构体,成员是保存错误的执行函数
type panicContext struct {
function string
}
// 创建一个保护函数ProtectRun
func ProtectRun(entry func()) {
defer func() { // 延迟处理函数
err := recover() // 发生宕机时,recover()获取panic传入的上下文并打印。defer延迟调用闭包
switch err.(type) { // 使用switch对变量err进行类型断言
case runtime.Error: // 运行时错误
fmt.Println("runtime error:", err)
default: // 非运行时错误
fmt.Println("error:", err)
}
}()
entry() // 对入参函数进行调用,当发生panic时,先调用defer后的闭包,再退出
}
func TestProtect(t *testing.T) {
fmt.Println("运行前")
ProtectRun(func() {
fmt.Println("手动宕机前")
panic(&panicContext{ // 使用panic手动触发一个错误,并把一个结构体附带信息传入,被ProtectRun函数的recover()捕获
"手动触发panic",
})
fmt.Println("手动宕机后") // panic之后的代码不再执行
})
ProtectRun(func() {
fmt.Println("赋值宕机前")
var a *int
*a = 1 // 模拟代码中空指针赋值造成的错误,此时Runtime层抛出错误,被ProtectRun函数的reover()捕获
fmt.Println("赋值宕机后") // panic之后的代码不再执行
})
fmt.Println("运行后")
}
2. panic和recover的关系
- 有panic没recover,程序宕机
- 有panic也有recover,程序不会宕机。执行完对应defer后,从宕机点退出当前函数,继续执行代码
以上是关于go语言学习笔记 — 基础 — 函数(12):防止程序崩溃—— 宕机恢复(recover)的主要内容,如果未能解决你的问题,请参考以下文章
go语言学习笔记 — 基础 — 函数:函数变量(把函数作为变量的值)