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有一 ...
随机推荐
- Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation
1.出现问题 查询数据时报如题错误 2.解决方案 建表时需指定字符集,例如: -- ---------------------------- -- Table structure for testTa ...
- 简要介绍WASAPI播放音频的方法
正文 填一下之前挖的坑,这回就说说怎么用WASAPI播放声音吧. 本文完整代码可以在以下链接找到 https://gitcode.net/PeaZomboss/learnaudios 目录是demo/ ...
- 一文搞懂 DevOps
前言 DevOps作为一个热门的概念,近年来频频出现在各大技术社区和媒体的文章中,备受行业大咖的追捧,也吸引了很多吃瓜群众的围观. 那么,DevOps是什么呢? 有人说它是一种方法,也有人说它是一种工 ...
- SpringBoot整合Mybatis、SpringBoot整合Spring Data JPA
Springboot Mybatis <?xml version="1.0" encoding="UTF-8"?> <project xmln ...
- 数字列表number,目标值target,找到number中两个不同数字之和等于target的数字,输出下标并顺序排列 ----笔试题记录扩展
一.思路: 输入:数字列表number,目标值target 判断条件:数字列表中两个不同数字相加等于target 输出:符合条件的两个数字的下标,下标顺序排列 方法1: def list(number ...
- [ARC107D] Number of Multisets
\(\text{Solution}\) 学习到了一些 \(dp\) 的 \(trick\) 设 \(f_{i,j}\) 表示用了 \(i\) 的元素,当前和为 \(j\) 的方案数 \(dp\) 有两 ...
- Invade the Mars
题目 网上大把 分析 显然不能简单直接最短路 城市被攻占的特点是:保护的城市都被攻占了 那么这个城市被攻占的最早时间必然是所有保护他的城市中最大的被攻占时间 于是我们可以 设 \(dis\) 表示军队 ...
- Python实战项目1-开发流程需求分析/基础环境搭建
软件开发流程 # 真正的企业里软件从立项到交付整个过程 -立项:确定公司要开发这个软件 公司高层 -软件来源 -产品经理设计出来的---->互联网项目 互联网公司 -用户(医院,政府部门,企业. ...
- SAP 删除始终使用选定的格式
修改默认格式 se38 SALV_BS_ADMIN_MAINTAIN
- ChatGPT is at capacity right now.ChatGPT Plus subscriber login Add your email for a personalized login link的解决办法
原因 你的ip地区用的人过多. 解决办法 在右侧页面填入邮箱,能收到邮件立刻就能登录,如果没有,就换地区试试,不行就等等吧 邮件示例: