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() }()

相关推荐
无限进步_7 分钟前
【C++】电话号码的字母组合:从有限处理到通用解法
开发语言·c++·ide·windows·git·github·visual studio
宸津-代码粉碎机8 分钟前
Spring Boot 4.0虚拟线程实战调优技巧,最大化发挥并发优势
java·人工智能·spring boot·后端·python
JJay.21 分钟前
Android Kotlin 协程使用指南
android·开发语言·kotlin
csbysj202027 分钟前
jQuery 捕获详解
开发语言
C++ 老炮儿的技术栈36 分钟前
GCC编译时无法向/tmp 目录写入临时汇编文件,因为设备空间不足,解决
linux·运维·开发语言·汇编·c++·git·qt
小码哥_常44 分钟前
一个Starter搞定六种防护,Spring Boot API的超强护盾来了
后端
三道渊1 小时前
进程通信与网络协议
开发语言·数据库·php
白露与泡影1 小时前
Java面试题库及答案解析(2026版)
java·开发语言·面试
codeejun1 小时前
每日一Go-44、Go网络栈深度拆解--从 TCP 到 HTTP 的资源复用艺术
网络·tcp/ip·golang
疯狂成瘾者1 小时前
Chroma向量数据库
开发语言·数据库·c#