【Go】panic/recover、编译器指令

news/2024/4/28 20:58:59/文章来源:https://blog.csdn.net/qq_55675216/article/details/137114876

https://blog.csdn.net/zhanggqianglovec/article/details/127906942
https://www.cnblogs.com/ricklz/p/14692264.html
https://zhuanlan.zhihu.com/p/624326431
学一点,整一点,基本都是综合别人的,弄成我能理解的内容

panic、recover

1、panic 能够改变程序的控制流,调用 panic 后会立刻停止执行当前函数的剩余代码,并在当前 Goroutine 中递归执行调用方的 defer(在panic()函数前面的已经执行过的defer语句);
2、recover 可以中止 panic 造成的程序崩溃。它是一个只能在 defer 中发挥作用的函数,在其他作用域中调用不会发挥作用;

1、panic 只会触发当前goroutine的defer
2、revoce 只有在defer中调用才能生效
3、panic 允许在defer中嵌套多次调用
4、recover没有传入参数,但是有返回值,返回值就是panic传递的值

使用场景

1、程序遇到无法执行下去的错误时,抛出错误,主动结束运行。
2、在调试程序时,通过 panic 来打印堆栈,方便定位错误。

error:可预见的错误
panic:不可预见的异常

需要注意的是,应该尽可能地使用error,而不是使用panic和recover。只有当程序不能继续运行的时候,才应该使用panic和recover机制。

panic有两个合理的用例。
1、发生了一个不能恢复的错误,此时程序不能继续运行。 一个例子就是 web 服务器无法绑定所要求的端口。在这种情况下,就应该使用 panic,因为如果不能绑定端口,啥也做不了。
2、发生了一个编程上的错误。 假如我们有一个接收指针参数的方法,而其他人使用 nil 作为参数调用了它。在这种情况下,我们可以使用panic,因为这是一个编程错误:用 nil 参数调用了一个只能接收合法指针的方法。

在一般情况下,我们不应通过调用panic函数来报告普通的错误,而应该只把它作为报告致命错误的一种方式。当某些不应该发生的场景发生时,我们就应该调用panic。

总结下panic的使用场景:
1、空指针引用
2、下标越界
3、除数为0
4、不应该出现的分支,比如default
5、输入不应该引起函数错误

示例

func main() {// 主线程中的defer函数并不会执行,因为子协程 panic后,主线程中的defer并不会执行defer println("in main")go func() {defer println("in goroutine")fmt.Println("子协程running")panic("子协程崩溃")}()time.Sleep(1 * time.Second)
}//输出
子协程running
in goroutine
panic: 子协程崩溃
func main() {defer fmt.Println("in main")defer func() {if err := recover(); err != nil {fmt.Println("occur error")fmt.Println(err)}}()panic("unknown err")}//输出
occur error
unknown err
in main

嵌套使用panic

func main() {defer fmt.Println("in main")defer func() {defer func() {panic("panic again and again")}()panic("panic again")}()panic("panic once")
}//输出
in main
panic: panic oncepanic: panic againpanic: panic again and again

panic源码

_panic定义

// _panic 保存了一个活跃的 panic
//
// 这个标记了 go:notinheap 因为 _panic 的值必须位于栈上
//
// argp 和 link 字段为栈指针,但在栈增长时不需要特殊处理:因为他们是指针类型且
// _panic 值只位于栈上,正常的栈指针调整会处理他们。
//
//go:notinheap
type _panic struct {argp      unsafe.Pointer // panic 期间 defer 调用参数的指针; 无法移动 - liblink 已知arg       interface{}    // panic的参数link      *_panic        // link 链接到更早的 panicrecovered bool           // panic是否结束aborted   bool           // panic是否被忽略
}

https://www.cnblogs.com/ricklz/p/14692264.html

编译器指令

https://zhuanlan.zhihu.com/p/624326431

编译器指令是由 Go 编译器处理的,不会影响到代码运行时的行为。在 Go 中,编译器指令都是以 //go: 开头的注释形式。

//go:notinheap 是一个编译器指令,它告诉编译器一个类型不能被分配在堆上。它常常用于运行时包(runtime package)。用户代码通常不应使用这个指令。
//go:embed:这个在 Go 1.16 版本引入,它让你可以在编译时将文件或目录嵌入二进制文件中。
//go:generate:它是一个生成器的指令,你可以在注释后提供一个命令供 go generate 命令执行生成代码。
//go:noinline:这个指令阻止编译器内联一个函数。
//go:linkname:这个指令允许将一个局部函数链接到另一个函数。
//go:directives:你可以查看包含指令列表的文档。

//go:build是在Go 1.17中引入的新编译器指令,用于替代旧的// +build条件编译标签。此//go:build nosyn表示向编译器指示仅在存在nosyn标签时才构建特定的文件。
可以使用如下命令进行编译go build -tags=nosyn

//go:noescape 禁止变量逃逸
变量逃逸是指 编译器将自动地将超出自身生命周期的变量,从函数栈转移到堆中。 golang就是自动将函数外部引用的变量转义到堆栈中,从而保障其他地方使用不会为空或者异常。
如果变量不逃逸,GC压力就会很小,提升性能;

//go:norace 跳过竞态检测
由于Goroutine很方便写并行逻辑,但是往往我们再代码中需要通过go run -race xxx.go测试是否有竞态,会导致编译慢,如果加上norace就可以跳过;

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

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

相关文章

QT文件读写操作和内容提取

访问IO设备,需要先调用open()来设置正确的OpenMode(例如ReadOnly或ReadWrite) 打开设备后后,使用write() 或putChar() 写入数据到文件和设备,并通过调用read(),readLine() 或readAll() 进行读取;使用完设备后&#xf…

离线数仓(八)【DWD 层开发】

前言 1、DWD 层开发 DWD层设计要点: (1)DWD层的设计依据是维度建模理论(主体是事务型事实表(选择业务过程 -> 声明粒度 -> 确定维度 -> 确定事实),另外两种周期型快照事实表和累积型…

【自我提升】一、Hyperledger Fabric 概念梳理

写在前面:最近因为业务需要,开始学习Hyperledger Fabric了,做java全栈工程师可真难搞。现在算是啥类型的都在涉及了,现在这个技术啥都不懂,就先开个学习专栏,记录记录。顺带也给各位道友参考参考。 目录 …

【Bug】记录2024年遇到的Bug以及修复方案

--------------------------------------------------------分割线 2024.3.22------------------------------------------------------- 1、load_sample_image raise AttributeError(“Cannot find sample image: %s” % image_name) AttributeError: Cannot find sample imag…

[linux初阶][vim-gcc-gdb] OneCharter: vim编辑器

一.vim编辑器基础 目录 一.vim编辑器基础 ①.vim的语法 ②vim的三种模式 ③三种模式的基本切换 ④各个模式下的一些操作 二.配置vim环境 ①手动配置(不推荐) ②自动配置(推荐) vim是vi的升级版,包含了更加丰富的功能. ①.vim的语法 vim [文件名] ②vim的三种模式 命令…

WPF —— DockPanel、ProgressBar 控件详解

ProgressBar 控件详解 1Progress bar简介 ProgressBar:进度条控件。 WPF带有一个方便的控件用于显示进度,称ProgressBar。它的工作原理就是设置最小值和最大值然后通过递增一个值,这样就可以直观的显示当前进度情况。 2 Progress bar常用的…

DFS:从递归去理解深度优先搜索

一、深入理解递归 二、递归vs迭代 三、深入理解搜索、回溯和剪枝 四、汉诺塔问题 . - 力扣&#xff08;LeetCode&#xff09; class Solution { public: //笔试题&#xff0c;不讲武德&#xff0c;CAvoid move(int n,vector<int>& A, vector<int>& B, ve…

前端实现浏览器自定义滚动条

前言&#xff1a; 最近有个项目&#xff0c;产品觉得浏览器默认滚动条太丑了。想美化一下&#xff0c;比如自定义颜色&#xff0c;加上圆角&#xff0c;宽高都要更改一下。我查了资料和文档总结了一下 写法&#xff0c;特此记录以便之后使用。 浏览器滚动条api 总结&#xff…

【爬取网易财经文章】

引言 在信息爆炸的时代&#xff0c;获取实时的财经资讯对于投资者和金融从业者来说至关重要。然而&#xff0c;手动浏览网页收集财经文章耗时费力&#xff0c;为了解决这一问题&#xff0c;本文将介绍如何使用Python编写一个爬虫程序来自动爬取网易财经下关于财经的文章 1. 爬…

代码随想录 Day-25

力扣题目 509.斐波那契数 思路 很理所当然的&#xff0c;可以使用递归的方式其次是用动态规划的方式&#xff0c;动态规划的核心就是递推公式。 那么递推和递归一字之差&#xff0c;有什么区别呢&#xff1f;&#xff08;递推和递归的区别&#xff09; 1、递归 class Solutio…

Java项目:77 springboot母婴商城

作者主页&#xff1a;源码空间codegym 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 本课题后端使用SpringBoot Spring Cloud框架&#xff0c;前端采用html&#xff0c;JQuery&#xff0c;JS&#xff0c;DIVCSS技术进行编程&…

Redis中AOF文件重写与同步

AOF文件的写入与同步 Redis服务器进程就是一个时间循环(loop),这个循环中的文件时间负责接收客户端的命令请求&#xff0c;以及向客户端发送命令回复&#xff0c;而时间事件则负责执行像serverCron函数这样需要定时运行的函数。因为服务器在处理文件事件时可能会执行些命令&am…

【Java程序设计】【C00416】基于(JavaWeb)Springboot的客户管理系统(含论文)

基于&#xff08;JavaWeb&#xff09;Springboot的客户管理系统&#xff08;含论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;已经做了六年的毕业设计程序开发&#xff0c;开发过上千…

C# 文件操作

文章目录 C# 文件操作创建文件运行结果 写入文件程序文件运行结果 WriteAllLines-写入多行运行结果 追加字符串运行结果追加多行字符串 读取文件ReadAllText运行结果 ReadAllLines-用数组接收读取的内容运行结果 采用流&#xff08;Stream&#xff09;的方式来读取内容运行结果…

stm32平衡车

目录 一.所需材料 二.PID算法&#xff08;简单说明&#xff09; 直立环 速度环 串级PID 三.使用到的外设 1.定时器输出比较-PWM 2.定时器编码器模式 3.编码器读取速度 4.电机驱动函数 5.外部中断 四、小车 调试 一.所需材料 1.陀螺仪MPU6050--读取三轴的加速度…

C++:梦的开始——创建第一个hello world(1)

我这里使用的编写代码的工具是Start Experimental Instance of Visual Studio 2022 你可以去微软的官网上寻找&#xff0c;并且安装 部署项目 项目就是一个文件夹&#xff0c;他将我们的数据都放到了里面&#xff0c;这就是一个项目 在Visual Studio 2022中 选择c 的空项目&a…

【Linux 08】进程概念

文章目录 &#x1f308; 01. 基本概念&#x1f308; 02. 描述进程 PCB&#x1f308; 03. 使用 ./ 的方式创建进程&#x1f308; 04. ps 查看进程&#x1f308; 05. getpid / getppid 获取进程标识符&#x1f308; 06. kill 终止指定进程&#x1f308; 07. fork 创建子进程&…

python学习14:python中的表达式

python中的表达式 1.表达式是什么呢&#xff1f; 表达式就是一个具有明确结果的代码语句&#xff0c;如11、type(‘字符串’)、3*5等 在定义变量的时候&#xff0c;如age108,等号右侧的就是表达式&#xff0c;也就是有具体的结果&#xff0c;将结果赋值给了等号左侧的变量 2.…

Linux 系统基础操作命令

当前市面上常见的系统&#xff1a;Windows、Linux、Mac OS、Android、IOS…… Linux 不太适合日常使用&#xff0c;但是非常适合用于开发。因此作为一个程序猿来说&#xff0c;Linux 都是务必要掌握的。 Linux 介绍 Linux 发行版 目前市面上比较知名的发行版有&#xff1a;R…

DNS隧道攻击

什么是DNS隧道&#xff1f; DNS隧道是一种网络通信技术&#xff0c;它利用DNS&#xff08;Domain Name System&#xff0c;域名系统&#xff09;协议来建立隐蔽的通信通道。在正常情况下&#xff0c;DNS协议主要用于将域名解析为IP地址&#xff0c;但攻击者可以通过构造特殊的…