Go异常处理机制panic和recover
recover
使用panic抛出异常后, 将立即停止当前函数的执行并运行所有被defer的函数,然后将panic抛向上一层,直至程序crash。但是也可以使用被defer的recover函数来捕获异常阻止程序的崩溃,recover只有被defer后才是有意义的。
func main() {
print(123)
print(456)
panic("throw an error")
print(678) //IDE会有提示: Unreachable code
}
结果:
123456panic: throw an error
goroutine 1 [running]:
main.main()
/Users/shuangcui/explore/panicandrecover.go:31 +0x67
使用recover()捕获异常:
func main() {
print(123)
defer func() {
if err := recover(); err != nil {
print("recover it")
}
}()
print(456)
panic("throw an error")
print(678) //IDE会有提示: Unreachable code
}
结果为:
123456recover it
如果有两个recover,则捕获异常的是后一个
func main() {
print(123)
defer func() {
if err := recover(); err != nil {
print("recover it")
}
}()
defer func() {
if err := recover(); err != nil {
print("复原!")
}
}()
print(456)
panic("throw an error")
print(678) //IDE会有提示: Unreachable code
}
结果为:
123456复原!
panic之后的任何代码都不会继续执行
前提是panic不在if里面
package main
import "fmt"
func main() {
defer_call()
fmt.Println("333 Helloworld")
}
func defer_call() {
defer func() {
fmt.Println("11111")
}()
defer func() {
fmt.Println("22222")
}()
defer func() {
if r := recover(); r != nil {
fmt.Println("Recover from r : ", r)
}
}()
defer func() {
fmt.Println("33333")
}()
fmt.Println("111 Helloworld")
panic("Panic 1!")
//使用panic抛出异常后, 将立即停止当前函数的执行并运行所有被defer的函数,然后将panic抛向上一层, 直至程序crash
//但是也可以使用被defer的recover函数来捕获异常阻止程序的崩溃,recover只有被defer后才是有意义的。
panic("Panic 2!") //panic1之后的panic2没有任何机会会被执行, panic2之后的任何代码更没有任何机会被执行
fmt.Println("222 Helloworld")
}
输出为:
111 Helloworld
33333
Recover from r : Panic 1!
22222
11111
333 Helloworld
对于goroutine中的panic,协程外面的recover是无法恢复的;goroutine中的recover,同样无法恢复协程外的panic
但协程中的recover可以恢复协程中的panic
package main
import (
"fmt"
"time"
)
func main() {
go func() {
defer func() {
if err := recover(); err != nil {
fmt.Println("recover err:", err)
}
}()
panic("里面出错了")
}()
//panic("外面出错了")
time.Sleep(1 * time.Second)
}
输出为:
recover err 里面出错了
主方法中的recover,也可以恢复子方法里的panic
但如果go subfunc(),则同样无法捕获subfunc中的异常
func main() {
fmt.Println(123)
defer fmt.Println(999)
defer func() {
if err := recover(); err != nil {
fmt.Println("恢复异常:",err)
}
}()
subfunc()
}
func subfunc() {
defer fmt.Println(888)
panic("出现了bug")
defer fmt.Println(456)
}
结果为:
123
888
恢复异常: 出现了bug
999
因为panic发生的时候,panic函数后面的语句都不会执行了,所以recover函数不能放在panic语句后面执行,而要放在defer函数中执行。
使用 panic 抛出异常后,函数执行将从调用 panic 的地方停止,如果函数内有 defer 调用,则执行 defer 后边的函数调用,如果 defer 调用的函数中没有捕获异常信息,这个异常会沿着函数调用栈往上传递,直到 main 函数仍然没有捕获异常,将会导致程序异常退出
如何区别使用 panic 和 error 两种方式?
惯例是:导致关键流程出现不可修复性错误的使用 panic ,其他使用 error 。
panic 和 recover 的组合有如下特性:
-
有 panic 没 recover ,程序宕机。 -
有 panic 也有 recover ,程序不会宕机,执行完对应的 defer 后,从宕机点退出当前函数后继续执行。
recover能捕获所有错误吗?
不能!
Go 有哪些无法恢复的致命场景?
像
-
并发读写 map fatal error: concurrent map read and map write -
堆栈内存耗尽(如递归)
runtime: goroutine stack exceeds 1000000000-byte limit
runtime: sp=0xc0200e1bf0 stack=[0xc0200e0000, 0xc0400e0000]
fatal error: stack overflow
-
将 nil 函数作为 goroutine 启动 fatal error: go of nil func value -
goroutines 死锁 fatal error: all goroutines are asleep - deadlock! -
线程超过设置的最大限制 fatal error: thread exhaustion -
超出可用内存 fatal error: runtime: out of memory
总之 都会报fatal error:xxxxxxxx
拓展&参考:
golang panic和recover 实现原理[1]
Go 学习笔记(19)— 函数(05)[如何触发 panic、触发 panic 延迟执行、panic 和 recover 的关系][2]
Go 语言踩坑记——panic 与 recover[3]
参考资料
golang panic和recover 实现原理: https://blog.csdn.net/u010853261/article/details/102761955
[2]Go 学习笔记(19)— 函数(05)[如何触发 panic、触发 panic 延迟执行、panic 和 recover 的关系]: https://blog.csdn.net/wohu1104/article/details/105571916
[3]Go 语言踩坑记——panic 与 recover: https://xiaomi-info.github.io/2020/01/20/go-trample-panic-recover/
本文由 mdnice 多平台发布
相关文章:
Go异常处理机制panic和recover
recover 使用panic抛出异常后, 将立即停止当前函数的执行并运行所有被defer的函数,然后将panic抛向上一层,直至程序crash。但是也可以使用被defer的recover函数来捕获异常阻止程序的崩溃,recover只有被defer后才是有意义的。 func main() { p…...
QMainwindow窗口
QMainwindow窗口 菜单栏在二级菜单中输入中文的方法给菜单栏添加相应的动作使用QMenu类的API方法添加菜单项分隔符也是QAction类 工具栏状态栏停靠窗口 菜单栏 只能有一个, 位于窗口的最上方 关于顶级菜单可以直接在UI窗口中双击, 直接输入文本信息即可, 对应子菜单项也可以通…...
P5735 【深基7.例1】距离函数
题目描述 给出平面坐标上不在一条直线上三个点坐标 ( x 1 , y 1 ) , ( x 2 , y 2 ) , ( x 3 , y 3 ) (x_1,y_1),(x_2,y_2),(x_3,y_3) (x1,y1),(x2,y2),(x3,y3),坐标值是实数,且绝对值不超过 100.00,求围成的三角形周长。保留两…...
prometheus告警发送组件部署
一、前言 要实现Prometheus的告警发送需要通过alertmanager组件,当prometheus触发告警策略时,会将告警信息发送给alertmanager,然后alertmanager根据配置的策略发送到邮件或者钉钉中,发送到钉钉需要安装额外的prometheus-webhook…...
CAPL - XML和TestModule结合实现测试项可选
目录 目的:是否想实现如下面的功能呢? 一、.can和.cin文件中函数开发...
Latex安装与环境配置(TeXlive、TeXstudio与VS code的安装)编译器+编辑器与学习应用
TeXlive 配置Tex排版系统需要安装编译器+编辑器。TeX 的源代码是后缀为 .tex 的纯文本文件。使用任意纯文本编辑器,都可以修改 .tex 文件:包括 Windows 自带的记事本程序,也包括专为 TeX 设计的编辑器(TeXworks, TeXmaker, TeXstudio, WinEdt 等),还包括一些通用的文本编…...
STM32 F103C8T6学习笔记3:串口配置—串口收发—自定义Printf函数
今日学习使用STM32 C8T6的串口,我们在经过学习笔记2的总结归纳可知,STM32 C8T6最小系统板上有三路串口,如下图: 今日我们就着手学习如何配置开通这些串口进行收发,这里不讲串口通信概念与基础,可以自行网上…...
python中字符串内建函数篇4
一、ljust() 语法:str.ljust(width,[fillchar]) 参数说明: width – 指定字符串长度。 fillchar – 填充字符,默认为空格。 返回值:返回一个原字符串左对齐,并使用空格填充至长度 width 的新字符串。如果指定的长度小于原字符串…...
并发下如何使用redis存储列表数据
1、问题 今天在工作中遇到一个问题,需要查询表A,需要根据每天所处小时所在时段,返回不同的记录给前端展示,如0-2时是在昨日0到2时生成的记录,而2-4时则是在昨日2-4时生成的记录,每条记录有一个唯一的id。表…...
Leecode螺旋矩阵 II59
59.螺旋矩阵II 题目建议: 本题关键还是在转圈的逻辑,在二分搜索中提到的区间定义,在这里又用上了。 题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 文章讲解:代码随想录 视频…...
echarts 横向柱状图
<template><div ref"chart" style"height: 100%"></div> </template><script> import * as echarts from "echarts"; var cate ["质量通病1", "质量通病2", "质量通病3", "质…...
Vue3 —— to 全家桶及源码学习
该文章是在学习 小满vue3 课程的随堂记录示例均采用 <script setup>,且包含 typescript 的基础用法 前言 本篇主要学习几个 api 及相关源码: toReftoRefstoRaw 一、toRef toRef(reactiveObj, key) 接收两个参数,第一个是 响应式对象…...
(第三篇) ansible-kubeadm在线安装高可以用集群()
ansible可以安装的KS8版本如下: 请按照此博客中的内容操作后,才可以通过下面的命令查询到版本。 [rootk8s-master01 ~]# yum list kubectl --showduplicates | sort -r kubectl.x86_64 1.20.0-0 kubern…...
flutter开发实战-颜色Color与16进制转换
flutter开发实战-颜色Color与16进制转换 一、颜色Color与16进制转换 代码如下 import dart:ui; class ColorUtil {/// 十六进制颜色,/// hex, 十六进制值,例如:0xffffff,/// alpha, 透明度 [0.0,1.0]static Color hexColor(int hex, {doub…...
Linux(进程地址空间)
进程地址空间 程序地址空间进程地址空间 程序地址空间 在Linux环境下,我们可以对上述程序空间地址进行验证: 运行程序,可以看到,我们就可以很好看出程序的地址空间的排布了: 进程地址空间 严格来说,我们…...
VLAN监控及常见问题排查
局域网,我们通常称为LAN,是一种由基于同一地理位置的设备组成的网络,可实现它们之间的通信,局域网的虚拟对应物是虚拟局域网或 VLAN。VLAN 增强了 LAN,提供了进行更改的灵活性、更高的可扩展性和更好的安全性。 使用 …...
PromQL实现Actuator获取的JVM指标的Full GC次数监控
Spring Boot 版本需要2.0.0或更高版本。 添加Micrometer Prometheus registry依赖: <dependency><groupId>io.micrometer</groupId><artifactId>micrometer-registry-prometheus</artifactId> </dependency>在application.properties中开…...
3.正则表达式
3.1什么是正则表达式 ●正则表达式( Regular Expression) 是用于匹配字符串中字符组合的模式。在JavaScript中, 正则表达式也是对象 ●通常用来查找、替换那些符合正则表达式的文本,许多语言都支持正则表达式 ●正则表达式在JavaScript中的使用场景: ➢…...
【学习FreeRTOS】第3章——FreeRTOS移植及配置文件
1.FreeRTOS源码简介 【一级目录:/】以下FreeRTOS的源码,其中,FreeRTOS文件夹最为重要,代笔FreeRTOS内核 【二级目录:/FreeRTOS】以下为FreeRTOS文件夹的内容,比较重要的有Demo文件夹和Source文件夹 【三级…...
Java算法_ LRU 缓存(LeetCode_Hot100)
题目描述:请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 获得更多?算法思路:代码文档,算法解析的私得。 运行效果 完整代码 import java.util.HashMap; import java.util.Map;/*** 2 * Author: L…...
shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...
蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...
打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
一、方案背景 在现代生产与生活场景中,如工厂高危作业区、医院手术室、公共场景等,人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式,存在效率低、覆盖面不足、判断主观性强等问题,难以满足对人员打手机行为精…...
STM32---外部32.768K晶振(LSE)无法起振问题
晶振是否起振主要就检查两个1、晶振与MCU是否兼容;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容(CL)与匹配电容(CL1、CL2)的关系 2. 如何选择 CL1 和 CL…...
HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...
MySQL 主从同步异常处理
阅读原文:https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主,遇到的这个错误: Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一,通常表示ÿ…...
LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)
在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...
书籍“之“字形打印矩阵(8)0609
题目 给定一个矩阵matrix,按照"之"字形的方式打印这个矩阵,例如: 1 2 3 4 5 6 7 8 9 10 11 12 ”之“字形打印的结果为:1,…...
