go 语言的宕机恢复(recover)
go 语言中的三种报错机制
第一种,也就是常说的 error 类型错误,不需要 recover 拯救,处理方式自己决定
第二种,panic 和 recover 是紧密集合的,有点类似 try catch,recover 能捕获到 panic
第三种,一些 Go 语言系统级别的错误,比如发生死锁,数据竞争,这种错误程序会立刻报错,无法 recover
recove 的作用
在 go 语言中,错误一般会由 error 触发,但是如果比较严重的错误(通常是没有恰当处理的 error,也可是手动触发) 会造成 panic 。 一旦主程序 panic ,会导致整个程序挂掉。如果这个错误不是那么严重,我们希望程序可以继续往下执行,而不是整个程序挂掉。
- 用
recover函数,对panic错误进行拦截,避免上传给主函数,进而避免整个程序挂掉。 - 可以在程序崩溃前,做一些操作,举个例子,当 web 服务器遇到不可预料的严重问题时,在崩溃前应该将所有的连接关闭,如果不做任何处理,会使得客户端一直处于等待状态。
下面例子
如果给 out 函数传入两个相同的形参,就会引发 panic。
如果没有 recover 拦截,fmt.Print 这行是执行不到的。
func main() {
Out(1, 1)
fmt.Println("*******此行函数依然能继续执行******")
}
func Out(numb1, numb2 int) bool {
defer func() {
if r := recover(); r != nil { # 在此处对panic进行拦截,不会将错误继续上报上去。
fmt.Println("异常已扑捉,避免继续往上层传递")
}
}()
if numb1 == numb2 {
panic("两个数不能相等")
}
return numb1 > numb2
}
知识点
- recover 仅在延迟函数
defer中有效 - 因为
Go语言没有异常系统,其使用 panic 触发宕机类似于其他语言的抛出异常,recover 的宕机恢复机制就对应其他语言中的 try/catch 机制。 - 谨记一点
recover只能恢复本协程的panic。
注意:即使是子协程内引发的 panic 依然会导致主程序的挂掉,如下面的例子
func main() {
go OutOne()
go OutTwo()
time.Sleep(time.Minute)
}
func OutOne() {
panic("错误")
}
func OutTwo() {
for i := 0; i < 10; i++ {
time.Sleep(time.Second)
fmt.Print("****此处继续执行***")
}
}

进阶
那么上面情况该怎么解决?
其实就是在发生 panic 的协程里面,用 recover 进行拦截。让它传不到主函数。
func main() {
go OutOne()
go OutTwo()
time.Sleep(time.Minute)
}
func OutOne() {
defer func() {
if r := recover(); r != nil {
fmt.Println("OutOne 的报错已经别扑捉", r)
}
}()
panic("错误")
}
func OutTwo() {
for i := 0; i < 10; i++ {
time.Sleep(time.Second)
fmt.Println("****此处继续执行***")
}
}
当panic、defer和子函数混合使用时的执行顺序
func f() {
fmt.Println("打开文件b")
defer func() {
fmt.Println("关闭文件b")
}()
panic("文件b读取异常")
}
func main() {
fmt.Println("打开文件a")
defer func() { fmt.Println("关闭文件a") }()
f()
fmt.Println("文件正常执行")
}
# 输出
打开文件a
打开文件b
关闭文件b
关闭文件a
panic: 文件b读取异常
- 记住这个例题,当
go语言发生panic时,会首先执行已经“进栈”的defer函数,最后然后在报出panic的错误。传给上层的函数。 - 当子函数发生
panic的时候,函数依然是会先执行已经“进栈”的defer函数,而爆出panic。
defer
在 go的代码中,defer 有点类似于压栈操作,只有被执行到了,才会入栈(延迟执行),但是实际上,defer函数是编译过程中,通过调整代码顺序实现
错误日志如何查看
package main
import "log"
func main() {
err := funcA()
if err != nil {
log.Println("日志输出错误")
}
}
func funcA() error {
panic("错误")
}
输出:

- 观察错误输出顺序,错误就是一个入栈的过程,会从底到上的打印,直到遇到
recover。 - 日志能不能输出这条错误,要看这条日志能不能走到。
参考文献
go 语言的宕机恢复(recover)的更多相关文章
- Vertica集群单节点宕机恢复方法
Vertica集群单节点宕机恢复方法 第一种方法: 直接通过admintools -> 5 Restart Vertica on Host 第二种方法: 若第一种方法无法恢复,则清空宕机节点的c ...
- mysql group replication 主节点宕机恢复
一.mysql group replication 生来就要面对两个问题: 一.主节点宕机如何恢复. 二.多数节点离线的情况下.余下节点如何继续承载业务. 在这里我们只讨论第一个问题.也就是说当主结点 ...
- Go语言 异常panic和恢复recover用法
Go语言 异常panic和恢复recover用法 背景:Go语言追求简洁优雅,所以,Go语言不支持传统的 try…catch…finally 这种异常,因为Go语言的设计者们认为,将异常与控制结构混在 ...
- 存在单点故障的namenode宕机恢复测试
前提:如果namenode没有做HA,那么至少应该启用secondarynamenode,以便namenode宕机之后手动恢复数据 实验环境:3个节点(cenos 6.10) 测试前数据: 1.为了确 ...
- HBase–RegionServer宕机恢复原理
Region Server宕机总述 HBase一个很大的特色是扩展性极其友好,可以通过简单地加机器实现集群规模的线性扩展,而且机器的配置并不需要太好,通过大量廉价机器代替价格昂贵的高性能机器.但也正因 ...
- drbd虚拟机宕机恢复方法
问题现象 云南计算节点YN-ec-compute-19因系统盘损坏宕机且操作系统无法恢复,其上本地虚拟机无法疏散且无法迁移 拟采用drbd备份的数据对compute19上的虚拟机进行恢复 恢复方法 1 ...
- CDH集群主节点宕机恢复
1 情况概述 公司的开发集群在周末莫名其妙的主节点Hadoop-1的启动固态盘挂了,由于CM.HDFS的NameNode.HBase的Master都安装在Hadoop-1,导致了整个集群都 ...
- MySQL - 高可用性:少宕机即高可用?
我们之前了解了复制.扩展性,接下来就让我们来了解可用性.归根到底,高可用性就意味着 "更少的宕机时间". 老规矩,讨论一个名词,首先要给它下个定义,那么什么是可用性? 1 什么是可 ...
- MySQL 系列(四) 主从复制、读写分离、模拟宕机、备份恢复方案生产环境实战
本章内容: 主从复制 简介原理 备份主库及恢复从库,配置从库生效 读写分离 如果主宕机了,怎么办? 双主的情况 MySQL 备份及恢复方案 备份单个及多个数据库 mysqldump 的常用参数 如何增 ...
- HBase RegionServer宕机处理恢复
本文分析RegionServer宕机后这个region server上的region是如何在其他region server上恢复的. region server宕机后发生了什么 HMaster有一 ...
随机推荐
- 学习Java Day4
今天重点学习了读取输入,然后在eclipse上试了很多次,存在一些还没能解决的问题,发现eclipse的使用十分不熟练, 明天重点学习一下如何使用eclipse.
- Java 调用 PaddleDetection 模型
文章地址 介绍 训练好的模型要给业务调用,deepjavalibrary/djl:Java 中与引擎无关的深度学习框架 (github.com) 可以完成这件事,它支持使用 Java 调用 PyTor ...
- 滴水2.c++构造 与 继承
1.构造函数特点 2.析构函数的特点: 析构函数前面必须有~ 3.继承 一个子类可以有多个父类 作业1. #include<stdio.h> struct DateInfo { int y ...
- BI工具术语表大全:从字母A-Z全面收录
谈到商业智能行业,变革是不可避免的.为了跟上步伐,各种各样的BI 解决方案正在快速迭代更新,以满足企业的数字化需求,那么市场上BI 工具种类繁杂,到底如何选择适合功能全面.满足自己企业运转情况的.合适 ...
- vue学习笔记:组件
组件是Vue.js最强大的功能之一.组件可以扩展HTML元素,封装可重用的代码,说白了就是一组可以重复使用的模板.组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽 ...
- 洛谷P3933 Chtholly Nota Seniorious
题目 https://www.luogu.com.cn/problem/P3933 顺便:中国珂学院 思路 看到此题先大喊一声"我永远喜欢珂朵莉!" 好了然后我们思考一下如何做此题 ...
- Git上手教程
不说费话,直接上链接 廖雪峰老师的GIT教程
- [JavaScript]对象数组 - 不完全整理
对象数组中查询属性为某个值的对象,使用Array.find() const array1 = [5, 12, 8, 130, 44]; const found = array1.find(elemen ...
- CentOS7 yum设置阿里源
1.备份 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup 2.下载新的CentOS-Base ...
- git基础代码获取
1.新建文件夹 2.使用命令git init 初始化 3.见你与远程厂库的连接,git remote add origin 远程仓库地址 4.将远程仓库代码拉去到本地,git fetch origin ...