go中异常处理流程
在 Go 语言中,panic
、recover
和 defer
是用于处理异常情况的关键字。它们通常一起使用来实现对程序错误的处理和恢复。
1. defer
语句
defer
用于在函数返回之前执行一段代码。被 defer
修饰的语句或函数会在包含 defer
的函数执行完毕后执行。defer
常用于资源清理、释放锁、关闭文件等操作。
func example() {
defer fmt.Println("This will be executed last")
fmt.Println("This will be executed first")
}
2. panic
和 recover
panic
用于引发运行时错误,导致程序崩溃。recover
用于捕获panic
引发的错误,并进行处理。
func example() {
defer func() {
if err := recover(); err != nil {
fmt.Println("Recovered from panic:", err)
}
}()
panic("This will cause a panic")
}
3. 示例
- 当程序执行到
panic
语句时,它会立即停止当前函数的执行,并开始沿调用堆栈向上执行所有的defer
语句。 - 执行
defer
语句时,将其推迟的函数或语句加入到一个栈中,但并不立即执行。 - 当所有的
defer
语句都被执行完毕后,程序会终止当前的函数执行,然后开始执行上一层函数的defer
语句,以此类推。 - 如果在
defer
语句执行的过程中发生了panic
,则panic
会被引发,但是在引发panic
之前,会先执行该层级的defer
语句。 - 如果有
recover
函数被调用,它会停止panic
的传播,并返回传递给panic
的值。
在 Go 中,一个协程(goroutine)出现 panic
不会直接影响其他协程的正常执行。Go 语言的设计目标之一是实现轻量级的并发,保持协程的独立性。因此,一个协程的 panic
不会波及到其他协程。
当一个协程发生 panic
时,通常会触发一系列的 defer
函数的执行,这提供了一种清理资源或记录日志等操作的机制。然后,Go 运行时系统会停止当前协程的执行,但不会影响其他正在运行的协程。
其他协程会继续执行,而不受 panic
影响。这是由于 Go 使用了处理异常的机制,而不是像传统的错误处理机制那样需要在每个函数中检查错误。在 Go 中,panic
主要用于表示程序遇到无法继续执行的错误情况。
下面是一个简单的例子,演示了一个协程的 panic
不会影响其他协程:
package main
import (
"fmt"
"sync"
"time"
)
func main() {
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
panicExample()
}()
// 启动另一个协程
wg.Add(1)
go func() {
defer wg.Done()
fmt.Println("Another goroutine is running.")
}()
// 等待所有协程结束
wg.Wait()
}
func panicExample() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
}()
fmt.Println("Start of panicExample")
time.Sleep(1 * time.Second)
panic("Something went wrong!")
fmt.Println("End of panicExample") // 不会执行到这里
}
在这个例子中,panicExample
函数中的 panic
不会影响另一个协程的正常执行。虽然一个协程中发生了 panic
,但其他协程仍然可以继续执行。
4. 总结
在Go中,runtime
包是负责处理Go运行时(runtime)的细节,包括垃圾回收、协程调度等。当出现panic
时,runtime
包会负责处理这些异常情况。
当程序中出现panic
时,Go运行时会按照以下步骤进行处理:
- 异常的传播:当一个函数发生
panic
时,该函数会立即停止执行,并将panic
传播到调用它的函数。这个过程会一直向上传播,直到被捕获或程序终止。 - 栈的展开(Unwinding):在
panic
发生时,Go运行时会开始展开调用栈(stack unwinding)。这意味着它会逆序执行当前调用栈中的函数,直到找到一个能够处理panic
的函数。 - 恢复(Recovery):在展开调用栈的过程中,Go运行时会寻找一个适当的
recover
函数来捕获并处理panic
。recover
函数是在当前协程的上下文中执行的,用于捕获并处理当前协程中的panic
。如果找到了一个recover
函数,并且它成功处理了panic
(即没有再次触发panic
),则程序会从发生panic
的位置开始继续执行。 - 如果没有找到适当的
recover
函数来处理panic
,程序将终止执行,并打印出相应的错误信息。
在处理panic
时,需要注意以下几点:
panic
通常表示程序中存在无法恢复的错误,因此应该尽量避免在正常的程序逻辑中使用panic
。panic
和recover
是用于处理程序中的异常情况,而不是用于控制程序的正常流程。recover
函数只能在协程(goroutine)的执行过程中使用,并且只能捕获当前协程中的panic
。- 当一个协程出现
panic
时,其它协程不会受到影响,会继续独立执行。

声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。
Author: mengbin
blog: mengbin
Github: mengbin92
cnblogs: 恋水无意
腾讯云开发者社区:孟斯特
go中异常处理流程的更多相关文章
- JAVA中的异常(异常处理流程、异常处理的缺陷)
异常处理流程 1)首先由try{...}catch(Exception e){ System.out.println(e); e.printStackTrace(); }finally{...}结构 ...
- Java中异常处理和设计
在程序设计中,进行异常处理是非常关键和重要的一部分.一个程序的异常处理框架的好坏直接影响到整个项目的代码质量以及后期维护成本和难度.试想一下,如果一个项目从头到尾没有考虑过异常处理,当程序出错从哪里寻 ...
- SpringMVC源码分析-400异常处理流程及解决方法
本文涉及SpringMVC异常处理体系源码分析,SpringMVC异常处理相关类的设计模式,实际工作中异常处理的实践. 问题场景 假设我们的SpringMVC应用中有如下控制器: 代码示例-1 @Re ...
- java中异常处理
看到一篇异常处理的好文章: Java异常处理机制主要依赖于try,catch,finally,throw,throws五个关键字. try 关键字后紧跟一个花括号括起来的代码块,简称try块.同理:下 ...
- ASP.NET中异常处理的注意事项
一.ASP.NET中需要引发异常的四类情况 1.如果运行代码后,造成内存泄漏.资源不可用或应用程序状态不可恢复,则引发异常.Console这个类中,有很多类似这样的代码: if ((value < ...
- springcloud Zuul中异常处理细节
Spring Cloud Zuul对异常的处理整体来说还是比较方便的,流程也比较清晰,只是由于Spring Cloud发展较快,各个版本之间有差异,导致有的小伙伴在寻找这方面的资料的时候经常云里雾里, ...
- 阶段5 3.微服务项目【学成在线】_day03 CMS页面管理开发_15-异常处理-异常处理流程
右侧是框架报的异常 不可预知的,例如数据库连不上这一类的.可以在map中制定某些类的异常,如果找不到就最右边的 99999的, 系统对异常的处理使用统一的异常处理流程: 1.自定义异常类型. 2.自定 ...
- Java中的流程控制(三)
关于Java中的流程控制 关于Java中的流程控制 4.do while语句 do while语句的功能和while语句差不多,只不过它是在执行完第一次循环后才检测条件表达式的值,这意味着包含在大括号 ...
- zigbee学习:示例程序SampleApp中通讯流程
zigbee学习:示例程序SampleApp中通讯流程 本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明. 参考链接: http://wjf88223.bl ...
- Android 儿子Activity在启动过程中的流程组件 && 儿子Activity在一个新的进程组件启动过程
1.儿子Activity在启动过程中的流程组件 在Android Activity启动过程http://blog.csdn.net/jltxgcy/article/details/35984557一文 ...
随机推荐
- 火山引擎 DataLeap:从短视频 APP 实践看如何统一数据指标口径
更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 短视频正在成为越来越多人发现世界的窗口,其背后的创作者生态建设是各大短视频 APP 不可忽视的重要组成部分. 为了 ...
- 【活动预告】数据集成引擎BitSail遇上CDC
BitSail是字节跳动开源数据集成引擎,于2022年10月26日宣布开源,可支持多种异构数据源间的数据同步,并提供离线.实时.全量.增量场景下全域数据集成解决方案.BitSail支撑了字节内部众多的 ...
- Axure 绘制表格添加删除
1.添加按钮:白底黑框,80X30,文本和命名均为"添加"; 2.数据表格(表头):1行5列,灰底黑框的表格作为表头,从左到右每个格子的文字分别为:姓名.性别.年龄.电话和操作: ...
- Flutter如何有效地退出程序
今天博主来谈一个开发Flutter App的小技巧--怎样有效地退出程序. 这种方法典型的应用场景就是用户许可协议的同意与否.从用户的角度讲,虽然大部分人都会无脑点击"同意",但我 ...
- Flutter 自定义组件实战之Cupertino(iOS)风格的复选框
继上一篇Flutter自定义组件的视频短课(视频地址: https://www.bilibili.com/video/BV1ap4y1U7UB/ )后,我们继续来聊自定义组件.视频中我为大家详解了Cu ...
- #1495:非常可乐(BFS+数论)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1495 BFS解法 题目 给三个数字 s n m s=n+m s在1到100之间 就是个倒水问题可以从第 ...
- AtCoder Beginner Contest 215 (个人题解 A~F)
比赛链接:Here AB水题, C - One More aab aba baa 题意: 给出字符串 \(s\) 和整数 \(k\) ,请输出字典序第 \(k\) 大的原字符串 \(s\) 的排序 思 ...
- The 18th Zhejiang Provincial Collegiate Programming Contest 补题记录(ACFGJLM)
补题链接:Here A. League of Legends 签到题,求和判断即可 ll suma, sumb; void solve() { ll x; for (int i = 1; i < ...
- java进阶(1)--final、常量
final是java的关键字,主要表示最终的 一.final修饰的类无法被继承
- jQuery组织后续事件 事件冒泡 事件委托 键被按下 批量操作 hover input 事件
1. jQuery绑定事件的方式 1. $('').click(function(){}) 2. $('').on('click', function(){}) 2. 阻止后续事件执行 1. retu ...