Go-知识recover

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() { // 假设函数为 Afunc() { // 假设函数为 B// gorecover(B)// (argp = B) != Aif 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.rhkb.cn/news/430143.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

无法删除选定的端口,不支持请求【笔记】

场景:在删除打印机端口时,提示:“无法删除选定的端口,不支持请求”,如下图所示。 以下以删除USB036端口为示例,操作步骤如下: 在注册表编辑器中,从以下注册表项中“计算机\HKEY_LO…

Spring中存储Bean的常见注解

目录 IoC & DI IOC(控制反转)详解 依赖注入的三种方式 IoC & DI IoC: Inversion of Control (控制反转), 也就是说 Spring 是⼀个"控制反转"的容器. 控制反转:也就是控制权反转. 什么的控制权发⽣了反转? 获得依赖对…

Python增强办公效率的11个实用代码段

如果你正在学习Python,那么你需要的话可以,点击这里👉Python重磅福利:入门&进阶全套学习资料、电子书、软件包、项目源码等等免费分享! 引言 在日常工作中,许多任务可以通过编程自动化来提高效率。本…

算法入门-贪心2

第八部分:贪心 561.数组拆分(简单) 题目:给定长度为 2n 的整数数组 nums ,你的任务是将这些数分成 n 对, 例如 (a1, b1), (a2, b2), ..., (an, bn) ,使得从 1 到 n 的 min(ai, bi) 总和最大。 返回该 最…

Three.js 3D人物漫游项目(下)

本文目录 前言最终效果1、效果回顾2、编写人物模型动画执行类并调用2.1 代码2.2 代码解读2.3 实例化动画类并调用2.4 效果2.4.1 休息动画2.4.2 跑步动画2.4.3 走路动画2.4.4 舞蹈1动画2.4.5 舞蹈2动画3、键盘控制动画3.1 站立休息、走、跑、舞蹈1、舞蹈2代码3.1.1 效果3.2 跳跃…

基于丹摩智算平台-手把手拿下经典目标检测模型 Faster-Rcnn

文章目录 1. 前言1. 1 丹摩智算平台1.2 经典目标检测模型 Faster-Rcnn 2. 前置准备2.1 WindTerm(远程连接服务器)2.2 项目源码 3. 服务器平台配置3.1 创建实例3.2 远程链接 4. Faster-rcnn 的环境配置4.1 上传文件,解压4.2 安装所需环境 5. 数…

华为HarmonyOS地图服务 1 -- 如何实现地图呈现?

如何使用地图组件MapComponent和MapComponentController呈现地图,效果如下图所示。 MapComponent是地图组件,用于在您的页面中放置地图。MapComponentController是地图组件的主要功能入口类,用来操作地图,与地图有关的所有方法从此…

基于PaddlePaddle复现的PeleeNet

转自AI Studio,原文链接:基于PaddlePaddle复现的PeleeNet - 飞桨AI Studio PeleeNet: An efficient DenseNet architecture for mobile devices 1. 简介 这是一个PaddlePaddle实现的PeleeNet。 PeleeNet是一个高效的卷积神经网络(CNN&…

数通。。。

通信:需要介质才能通信电话离信号塔(基站)越远,信号越弱。信号在基站之间传递。你离路由器越远,信号越差。一个意思 比如想传一张图片,这张图片就是数据载荷 网关,分割两个网络。路由器可以是网…

【贪心算法】贪心算法二

贪心算法二 1.最长递增子序列2.递增的三元子序列3.最长连续递增序列 点赞👍👍收藏🌟🌟关注💖💖 你的支持是对我最大的鼓励,我们一起努力吧!😃😃 1.最长递增子序列 题目链…

AI免费UI页面生成

https://v0.dev/chat v0 - UI设计 cursor - 编写代码 参考:https://www.youtube.com/watch?vIyIVvAu1KZ4 界面和claude类似,右侧展示效果和代码 https://pagen.so/

用uniapp 及socket.io做一个简单聊天 升级 9

比这之前优化了以下功能 上线通知 群聊里适时显示在线人数 约请好友 通过好友通过socket 相应端自动变化 PC端可以拉取摄象头拍照 PC端可以录音发送 拉起摄象头发送录象 <template><view class""><scroll-view scroll-y"true" class&…

【Linux篇】常用命令及操作技巧(基础篇)

&#x1f30f;个人博客主页&#xff1a;意疏-CSDN博客 希望文章能够给到初学的你一些启发&#xff5e; 如果觉得文章对你有帮助的话&#xff0c;点赞 关注 收藏支持一下笔者吧&#xff5e; 阅读指南&#xff1a; 开篇说明帮助命令常见的七个linux操作终端实用的技巧跟文件目录…

【深入理解SpringCloud微服务】了解微服务的熔断、限流、降级,手写实现一个微服务熔断限流器

【深入理解SpringCloud微服务】了解微服务的熔断、限流、降级&#xff0c;手写实现一个微服务熔断限流器 服务雪崩熔断、限流、降级熔断降级限流 手写实现一个微服务熔断限流器架构设计代码实现整体逻辑ProtectorAspect#aroundMethod(ProceedingJoinPoint)具体实现1、获取接口对…

智慧农业——InsectMamba利用状态空间模型对害虫进行分类

介绍 论文地址&#xff1a;https://arxiv.org/abs/2404.03611 害虫分类是农业中的一个重要问题。准确识别有害害虫可减少对作物的损害&#xff0c;确保粮食安全和环境的可持续发展。然而&#xff0c;害虫及其自然环境的高度拟态性和物种多样性使得视觉特征的提取极具挑战性。…

Centos7.9 使用 Kubeadm 自动化部署 K8S 集群(一个脚本)

文章目录 一、环境准备1、硬件准备&#xff08;虚拟主机&#xff09;2、操作系统版本3、硬件配置4、网络 二、注意点1、主机命名格式2、网络插件 flannel 镜像拉取2.1、主机生成公私钥2.2、为啥有 Github 还用 Gitee2.3、将主机公钥添加到 Gitee2.3.1、复制主机上的公钥2.3.2、…

< 微积分Calculus >

微积分 微分是把整体分拆为小部分来求它怎样改变 积分是把小部分连接在一起来求整体有多大&#xff0c;可以用来求面积、体积、中点和很多其他有用的东西。 lim极限 函数f(x) -> Q(x) y&#xff1a;x变量&#xff0c;f函数&#xff0c;Q(x)函数体&#xff08;多项式&am…

【Paper Reading】结合 NanoFlow 研究,优化大语言模型服务效率的探索

作者 王伟 PAI引擎团队 近年来&#xff0c;人工智能领域的快速发展推动了大型语言模型的广泛应用&#xff0c;随之而来的是对其服务效率的迫切需求。论文《NanoFlow&#xff1a;Towards Optimal Large Language Model Serving Throughput》提出了一种突破性的新型服务框架&…

CTF 技能树 LOG -GIT泄露 笔记

log 使用虚拟机kali操作 python2 安装 apt-get install python2 进入root用户&#xff0c;下载克隆git hack库 git clone https://github.com/BugScanTeam/GitHack sudo passwd root 修改root 命名密码为root 切换登录 su root 终端进入home/kali/GitHack/ python GitH…

2024年 AI大模型我该买一张什么卡?

有钱啥也不用说&#xff0c;买张最贵的就是了。对囊中羞涩的我还说&#xff0c;我该买张什么样的显卡呢&#xff1f; 我的旧显卡RTX1060 6G&#xff0c;满负荷消耗功率110多瓦&#xff0c;几乎达到设计最大TDP&#xff0c;周日时拿了朋友的RTX3060Ti 8G&#xff0c;发现是锁算…