Go-知识recover

news2024/9/22 7:05:49

Go-知识recover

  • 1. 介绍
  • 2. 工作机制
    • 2.1 recover 定义
    • 2.2 工作流程
    • 2.3 总结
  • 3. 原理
    • 3.1 recover函数的真正逻辑
    • 3.2 恢复逻辑
    • 3.3 生效条件
  • 4. 总结
    • 4.1 recover的返回值是什么?
    • 4.2 执行recover之后程序将从哪里继续运行?
    • 4.3 recover为什么一定要在defer中使用?
    • 4.4 recover为什么必须被defer直接调用才生效

1. 介绍

内置函数recover用于消除panic并使程序恢复正常。

recover的返回值是什么?
执行recover之后程序将从哪里继续运行?
recover为什么一定要在defer中使用?

2. 工作机制

2.1 recover 定义

与panic函数一样,recover函数也是一个内置函数
在这里插入图片描述

recover函数的返回值就是panic函数的参数,当程序产生panic时,recover函数就可用于消除panic,
同时返回panic函数的参数,如果程序没有发生panic,则recover函数返回nil.
如果panic函数参数为nil,那么仍然是一个有效的panic,此时recover函数仍然可以捕获panic,但返回值为nil。
recover函数必须且直接位于defer函数中才有效。
在这里插入图片描述

即使在defer函数中调用func,func中的recover也无法消除panic,必须是直接的defer中才行,而且不能嵌套:
在这里插入图片描述

2.2 工作流程

出现panic后,recover可以恢复程序正常的执行流程
在这里插入图片描述

黑色箭头代表征程执行流程,红色箭头表示出现了panic的执行流程。
当出现panic后,panic后续的代码不在被执行。
逐层执行defer,直到recover消除,或这到达最外层。
如果panic被recover了,那么别的goroutine是不会感知panic的。

2.3 总结

recover的几个要点:

  • recover函数调用必须要位于defer函数中,且不能出现在另一个嵌套函数中
  • recover函数成功处理异常后,无法再次回到本函数发生panic的位置上继续执行
  • recover函数可以消除本函数产生或收到的panic,上游函数感知不到panic的发生

当函数中发生panic并用recover函数恢复后,当前函数仍然会继续返回,对于匿名函数返回值,函数将返回相应类型的零值,对于具名返回值,
函数将返回当前已经存在的值。

3. 原理

3.1 recover函数的真正逻辑

recover内置函数实际上调用的是gorecover函数
src/runtime2.go
在这里插入图片描述

当panic不为空,而且panic没有被捕获,而且recover必须被defer直接调用,才会进行捕获处理。

3.2 恢复逻辑

gorecover函数通过协程数据结构中的_panic得到当前panic实例,如果当前panic的状态支持recover,则给该panic实例标记recoverd状态,
最后返回panic函数的参数。
当前执行的recover函数的defer函数是被gopanci执行的,defer函数执行结束后,在gopanic中会检查_panic的recoverd的状态,如果发现panic被恢复,
则gopanic将结束当前panic流程,将程序流程回复正常。
在这里插入图片描述

3.3 生效条件

if p != nil && !p.recovered && argp == uintptr(p.argp) {
		p.recovered = true    
		return p.arg
}

当前协程没有产生panic时,协程结构体中_panic的链表为空,也就是 pnil,不满足恢复条件。
假设函数包含多个defer函数,前面的defer函数通过recover函数消除panic后,函数中剩余的defer仍然会执行,但不能再次recover。也就是p.recoverd
true
内置函数recover没有参数,但是gorecover函数却有参数,gorecover中的参数为调用recover函数的参数地址,通常是defer 函数的参数地址。
_panic实例中也保存了当前defer函数的参数地址,如果二者一致,说明recover被defer函数直接调用。
在这里插入图片描述

func TestTwelve(t *testing.T) {
	defer func() { // 假设函数为 A
		func() { // 假设函数为 B
			// gorecover(B)
			// (argp = B) != A
			if err := recover(); err != nil {
				fmt.Println(err)
			}
		}()
	}()
	panic("panic")
}

在这里插入图片描述

4. 总结

4.1 recover的返回值是什么?

recover的返回值是panic的参数。

4.2 执行recover之后程序将从哪里继续运行?

将从defer中继续执行(不管是否发生panic,defer 都会执行)

4.3 recover为什么一定要在defer中使用?

如果recover函数不在defer函数中,那么recover函数可能出现在panic之前,也可能出现在panic之后。
出现在panic之前,因为找不到panic实例而无法生效。
出现在panic之后,代码没有机会执行,所以recover函数必须存在于defer函数中才会生效。

4.4 recover为什么必须被defer直接调用才生效

这个问题等价于:
为什么在defer函数中调用了函数A ,在A中的recover不会生效
为什么recover只能处理本函数中或者传递给本函数的panic

func TestTwelve(t *testing.T) {
	defer func() { 
		thirdPkg.Clean() // 调用第三方清理
	}()
	panic("panic")
}

有时我们会在代码里显式的触发panic,同时还往往会在defer函数里调用第三方的包清理资源,如果第三方包也使用了recover,那么我们触发的panic将会被拦截,
而且这种拦截可能是非预期。所以recover会被限定范围只能是defer直接调用才行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2154513.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2024年信息学奥赛CSP-J1入门组初赛真题试卷

2024年信息学奥赛CSP-J1入门组初赛真题试卷 题目总数:20 总分数:100 选择题 第 1 题 单选题 32位int类型的存储范围是( ) A. -2147483647 ~ 2147483647 B. -2147483647 ~ 2147483648 C. -2147483648 ~ 2147483647…

如何使用 React、TypeScript、TailwindCSS 和 Vite 创建 Chrome 插件

创建一个 Chrome 插件是一个有趣的项目,特别是当结合使用强大的工具如 React、TypeScript、TailwindCSS 和 Vite 时 在这篇文章中,我们将逐步引导完成整个过程,了解如何在 2024 年构建自己的 Chrome 插件。无论是经验丰富的开发者还是刚刚起…

C++ | Leetcode C++题解之第423题从英文中重建数字

题目&#xff1a; 题解&#xff1a; class Solution { public:string originalDigits(string s) {unordered_map<char, int> c;for (char ch: s) {c[ch];}vector<int> cnt(10);cnt[0] c[z];cnt[2] c[w];cnt[4] c[u];cnt[6] c[x];cnt[8] c[g];cnt[3] c[h] - …

JavaScript使用leaflet库显示信息窗口

前言 我们可千万不能忘记我们之前花的流程图哦&#xff0c;我们所有的计划都按照我们的流程图来去构建&#xff1b; 我们已经完成了&#xff0c;页面的加载&#xff0c;也已经完成获取用户当前的位置坐标&#xff0c;并且我们通过地图的API将当前的位置在地图中渲染出来&…

【每日刷题】Day128

【每日刷题】Day128 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 606. 根据二叉树创建字符串 - 力扣&#xff08;LeetCode&#xff09; 2. LCR 194. 二叉树的最近公…

TryHackMe 第3天 | Pre Security (中)

该学习路径讲解了网络安全入门的必备技术知识&#xff0c;比如计算机网络、网络协议、Linux命令、Windows设置等内容。上一篇中简短介绍了计算机网络相关的知识&#xff0c;本篇博客将记录 网络协议 部分。 How the web works? DNS in detail DNS (Domain name system&…

【数据结构】排序算法系列——快速排序(附源码+图解)

快速排序 接下来我们将要介绍的是排序中最为重要的算法之一——快速排序。 快速排序&#xff08;英语&#xff1a;Quicksort&#xff09;&#xff0c;又称分区交换排序&#xff08;partition-exchange sort&#xff09;&#xff0c;最早由东尼霍尔提出。快速排序通常明显比其…

XXL-JOB环境搭建

2.快速入门 2.1 下载源码 a.源码下载地址: github地址 gitee地址 2.2.环境搭建&#xff1a; a.初始化调度数据库: 1.请下载项目源码并解压&#xff0c;获取 “调度数据库初始化SQL脚本” 并执行即可 b.编译源码: 1.解压源码,按照maven格式将源码导入IDE, 使用maven进行…

【Python】使用国内镜像安装conda并创建python环境

conda介绍&#xff1a; Conda 是一个开源的包管理系统和环境管理系统&#xff0c;由 Continuum Analytics 开发。它的主要作用是简化科学计算中软件包和依赖的安装和升级&#xff0c;并允许用户轻松地在不同的环境中切换。Conda 的设计初衷是为了简化 Python 环境的搭建和管理&…

海洋大地测量基准与水下导航系列之二国外海底大地测量基准和海底观测网络发展现状(上)

海底大地控制网建设构想最先由美国斯克里普斯海洋研究所(Scripps Institution of Oceanography,SIO)提出&#xff0c;目前仅有少数发达国家具备相应技术条件。美国、日本、俄罗斯和欧盟等发达国家通过布测先进的海底大地控制网&#xff0c;不断完善海洋大地测量基准基础设施&am…

go 运行报错missing go.sum entry for module providing package

运行&#xff1a; #清理go.mod中不再需要的模块&#xff0c;并且会添加缺失的模块条目到go.sum中 go mod tidy

【全网最全】2024华为杯数学建模C题高质量成品查看论文!【附带全套代码+数据】

题 目&#xff1a; ___基于数据驱动下磁性元件的磁芯损耗建模 完整版获取&#xff1a; 点击链接加入群聊【2024华为杯数学建模助攻资料】&#xff1a;http://qm.qq.com/cgi-bin/qm/qr?_wv1027&kxtS4vwn3gcv8oCYYyrqd0BvFc7tNfhV7&authKeyedQFZne%2BzvEfLEVg2v8FOm%…

线段树优化dp,CF 413E - Maze 2D

目录 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 413E - Maze 2D 二、解题报告 1、思路分析 对于(li, l) -> (ri, r) …

nginx upstream转发连接错误情况研究

本次测试用到3台服务器&#xff1a; 192.168.10.115&#xff1a;转发服务器A 192.168.10.209&#xff1a;upstream下服务器1 192.168.10.210&#xff1a;upstream下服务器2 1台客户端&#xff1a;192.168.10.112 服务器A中nginx主要配置如下&#xff1a; log_format main…

接口加解密及数据加解密

目录 一、 加解密方式介绍 1.1 Hash算法加密 1.2. 对称加密 1.3 非对称加密 二、 我们要讲什么&#xff1f; 三、 接口加解密 四、 数据加解密 一、 加解密方式介绍 所有的加密方式我们可以分为三类&#xff1a;对称加密、非对称加密、Hash算法加密。 算法内部的具体实现…

Mysql高级篇(中)—— SQL优化之查询截取分析

SQL优化之查询截取分析 一、慢查询日志&#xff08;1&#xff09;简述&#xff08;2&#xff09;如何开启&#xff08;3&#xff09;慢查询日志分析工具介绍(了解)&#xff08;4&#xff09;官方工具 mysqldumpslow简述如何使用 二、SHOW PROCESSLIST三、&#xff08;了解&…

网络安全详解

目录 引言 一、网络安全概述 1.1 什么是网络安全 1.2 网络安全的重要性 二、网络安全面临的威胁 2.1 恶意软件&#xff08;Malware&#xff09; 2.2 网络钓鱼&#xff08;Phishing&#xff09; 2.3 中间人攻击&#xff08;Man-in-the-Middle Attack&#xff09; 2.4 拒…

让C#程序在linux环境运行

今晚花一些时间&#xff0c;总结net程序如何在linux环境运行的一些技术路线。 1、采用.Net Core框架 NET Core 使用了 .NET Core Runtime&#xff0c;它可以在 Windows、Linux 和 macOS 等多个操作系统上运行。可以采用Visual Studio生成Linux版本的dll。 在Linux系统中&…

救生圈检测系统源码分享

救生圈检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Visio…

Python基础学习(3)

目录 一&#xff0c;函数 1&#xff0c;函数的定义 2&#xff0c;函数的参数 1&#xff0c;默认值 2&#xff0c;传参 3&#xff0c;返回值 4&#xff0c;变量的作用域 5&#xff0c;函数的调用 二&#xff0c;常用数据结构 1&#xff0c;列表 列表的定义 列表的特性…