Golang异常处理机制

go语言使用error来处理错误,用panic和recover来处理异常

error

go语言的错误处理有两个发展阶段,以go1.13版本为分水岭,在1.13版本之前,标准库对error的支持非常有限,仅有errors.New()和fmt.Errorf()两个函数来构造errorString实例。在这个阶段,error处理存在一个非常大的问题:传递错误时,使用fmt.Errorf()传递捕获的error并为error增加上下文信息时,原error将和上下文的描述信息混杂在一起,导致原始的error信息丢失。

在go1.13版本,Go官方加强了对errors的支持,在进行错误传递的时候,采用链式传递的方式,将同一上下文的error链接起来,并且保留原始的error信息。通过在fmt.Errorf()中增加一个格式动词%w,来创建链式的error,并且提供errors.Unwarp()来拆解error。

创建错误的两种方式:

  1. errors.New(str string)

  2. fmt.Errorf("format string",a ...any)

我们可以通过以上两种方式来创建错误类型,第一种创建出来的是stringError,第二种方式创建出来的类型,取决于传入的格式动词,在1.13版本之前只能够创建stringError类型的错误。在1.13版本之后,通过传入格式动词%w,可以创建出warpError类型的错误,我们需要注意的是,传入的%w应该和传入的err来配对。

defer

不仅函数正常返回会执行被defer延迟的函数,函数中任意一个return语句、panic语句均会触发延迟函数。

defer的三大规则:

  1. 延迟函数的参数在defer语句出现时就已经确定了,延迟函数体中引用的变量,在编译的会绑定主函数中的对应变量,会获取变量的最终值。【对于指针函数的变量,复制的是地址值】

  2. 延迟函数按后进先出的顺序执行,即先出现的defer最后执行

  3. 延迟函数可能会操作主函数的具名返回值。【return的返回操作并不是原子性的,而是分为两个步骤:一是设置返回值,二是执行跳转,defer语句发生在跳转之前】(分析方向,先判断返回值的类型,是匿名还是具名,只有在defer语句中,对具名返回值进行更改的时候,才会修改返回值)

panic

panic的工作机制:每一个协程中都维护一个defer链表,执行过程中每遇到一个defer语句都会创建一个defer实例,并将这一个defer实例插入链表,函数退出时取出本函数创建的defer实例并执行。panic发生时,实际上是把程序的流程转向了这一个defer链表,程序专注于消费链表中的defer函数,当链表中的defer函数被消费完,再触发程序的退出。

我们在程序中一些可以预料到的、业务上的错误,可以通过定义err进行异常处理,处理err时,我们的程序是正常的,按照我们编写的逻辑顺序执行的。 而panic则用来处理不可预料到的错误和进行危险操作时触发panic。一旦程序发生panic,那么panic所在的函数体之后的代码将不会再执行,转而递归执行当前协程所有的defer函数,当前协程中的所有defer处理完成后,触发程序退出。如果panic执行过程中任意一个defer函数执行了recover(),那么panic的处理流程就会中止。程序继续执行上游函数中的代码。

recover

内置函数recover()用于消除panic并使程序回到正常的执行流程中。

recover的返回值是捕获到的panic()函数的参数

recover()执行之后,程序的执行流程转向上游函数,并且上游函数感知不到panic的发生。而发生panic的函数后面的代码不会被执行。【一旦发生惊慌,函数的执行流程就变了】

recover()函数必须直接位于defer函数中才有效。defer func() { recover() }()

相关推荐
程序猿DD2 小时前
OctaFuse Gateway 2.15.0:MCP 聚合、向量 Embeddings 与官方目录同步
后端·agent
余槐i4 小时前
PostgreSQL 函数索引报错 must be immutable:3种绕法与代价
数据库·后端·sql·postgresql·性能优化
需要8265 小时前
Spring Bean 生命周期:从实例化到销毁的完整钩子
java·后端·spring
死磕音视频6 小时前
让小模型做选择题:限定候选项并读取 logits 概率的入门实践(附 Python 代码)
开发语言·python·大模型·文本分类·transformers
凤山老林6 小时前
Spring Boot 接入国密 SM2/SM3/SM4 的一些实践记录
spring boot·后端·python
伯恩bourne7 小时前
Spring Boot Bean 注册的两种方式:@Component 家族 vs @Configuration + @Bean
java·spring boot·后端
张彦峰ZYF7 小时前
停顿短不等于延迟低:G1、ZGC 与低延迟服务的目标分野、代价账本与选型标定
后端·回收暂停、应用停止总时长·到达安全点、分配停滞·屏障吃吞吐、并发线程吃核心·并发窗口吃堆余量·分区式靠挑回收集兑现目标·染色指针式不支持压缩引用
pride.li8 小时前
第03章 Python 教程-基础语法:注释与变量
服务器·前端·后端·python·算法·计算机视觉
顽疲8 小时前
Java vue 养老系统源码详解:月账单 care_month_bill 与 Quartz 扣费 Job 实践
java·开发语言·vue.js·vue养老·springboot养老·java养老
Wang's Blog8 小时前
Java 项目实战: 交友项目 - 安装开发工具与环境准备
java·开发语言·交友