在 Go 语言中,panicrecoverdefer 是用于处理异常情况的关键字。它们通常一起使用来实现对程序错误的处理和恢复。

1. defer 语句

defer 用于在函数返回之前执行一段代码。被 defer 修饰的语句或函数会在包含 defer 的函数执行完毕后执行。defer 常用于资源清理、释放锁、关闭文件等操作。

func example() {
defer fmt.Println("This will be executed last")
fmt.Println("This will be executed first")
}

2. panicrecover

  • 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. 示例

  1. 当程序执行到 panic 语句时,它会立即停止当前函数的执行,并开始沿调用堆栈向上执行所有的 defer 语句。
  2. 执行 defer 语句时,将其推迟的函数或语句加入到一个栈中,但并不立即执行。
  3. 当所有的 defer 语句都被执行完毕后,程序会终止当前的函数执行,然后开始执行上一层函数的 defer 语句,以此类推。
  4. 如果在 defer 语句执行的过程中发生了 panic,则 panic 会被引发,但是在引发 panic 之前,会先执行该层级的 defer 语句。
  5. 如果有 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运行时会按照以下步骤进行处理:

  1. 异常的传播:当一个函数发生panic时,该函数会立即停止执行,并将panic传播到调用它的函数。这个过程会一直向上传播,直到被捕获或程序终止。
  2. 栈的展开(Unwinding):在panic发生时,Go运行时会开始展开调用栈(stack unwinding)。这意味着它会逆序执行当前调用栈中的函数,直到找到一个能够处理panic的函数。
  3. 恢复(Recovery):在展开调用栈的过程中,Go运行时会寻找一个适当的recover函数来捕获并处理panicrecover函数是在当前协程的上下文中执行的,用于捕获并处理当前协程中的panic。如果找到了一个recover函数,并且它成功处理了panic(即没有再次触发panic),则程序会从发生panic的位置开始继续执行。
  4. 如果没有找到适当的recover函数来处理panic,程序将终止执行,并打印出相应的错误信息。

在处理panic时,需要注意以下几点:

  • panic通常表示程序中存在无法恢复的错误,因此应该尽量避免在正常的程序逻辑中使用panic
  • panicrecover是用于处理程序中的异常情况,而不是用于控制程序的正常流程。
  • recover函数只能在协程(goroutine)的执行过程中使用,并且只能捕获当前协程中的panic
  • 当一个协程出现panic时,其它协程不会受到影响,会继续独立执行。

声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。

Author: mengbin

blog: mengbin

Github: mengbin92

cnblogs: 恋水无意

腾讯云开发者社区:孟斯特


go中异常处理流程的更多相关文章

  1. JAVA中的异常(异常处理流程、异常处理的缺陷)

    异常处理流程 1)首先由try{...}catch(Exception e){ System.out.println(e); e.printStackTrace(); }finally{...}结构 ...

  2. Java中异常处理和设计

    在程序设计中,进行异常处理是非常关键和重要的一部分.一个程序的异常处理框架的好坏直接影响到整个项目的代码质量以及后期维护成本和难度.试想一下,如果一个项目从头到尾没有考虑过异常处理,当程序出错从哪里寻 ...

  3. SpringMVC源码分析-400异常处理流程及解决方法

    本文涉及SpringMVC异常处理体系源码分析,SpringMVC异常处理相关类的设计模式,实际工作中异常处理的实践. 问题场景 假设我们的SpringMVC应用中有如下控制器: 代码示例-1 @Re ...

  4. java中异常处理

    看到一篇异常处理的好文章: Java异常处理机制主要依赖于try,catch,finally,throw,throws五个关键字. try 关键字后紧跟一个花括号括起来的代码块,简称try块.同理:下 ...

  5. ASP.NET中异常处理的注意事项

    一.ASP.NET中需要引发异常的四类情况 1.如果运行代码后,造成内存泄漏.资源不可用或应用程序状态不可恢复,则引发异常.Console这个类中,有很多类似这样的代码: if ((value < ...

  6. springcloud Zuul中异常处理细节

    Spring Cloud Zuul对异常的处理整体来说还是比较方便的,流程也比较清晰,只是由于Spring Cloud发展较快,各个版本之间有差异,导致有的小伙伴在寻找这方面的资料的时候经常云里雾里, ...

  7. 阶段5 3.微服务项目【学成在线】_day03 CMS页面管理开发_15-异常处理-异常处理流程

    右侧是框架报的异常 不可预知的,例如数据库连不上这一类的.可以在map中制定某些类的异常,如果找不到就最右边的 99999的, 系统对异常的处理使用统一的异常处理流程: 1.自定义异常类型. 2.自定 ...

  8. Java中的流程控制(三)

    关于Java中的流程控制 关于Java中的流程控制 4.do while语句 do while语句的功能和while语句差不多,只不过它是在执行完第一次循环后才检测条件表达式的值,这意味着包含在大括号 ...

  9. zigbee学习:示例程序SampleApp中通讯流程

    zigbee学习:示例程序SampleApp中通讯流程 本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明. 参考链接: http://wjf88223.bl ...

  10. Android 儿子Activity在启动过程中的流程组件 &amp;&amp; 儿子Activity在一个新的进程组件启动过程

    1.儿子Activity在启动过程中的流程组件 在Android Activity启动过程http://blog.csdn.net/jltxgcy/article/details/35984557一文 ...

随机推荐

  1. Seal 软件供应链防火墙 v0.2 发布,提供依赖项全局洞察

    Seal 软件供应链防火墙 v0.2 已于近日发布.这款产品旨在为企业提供代码安全.构建安全.依赖项安全及运行环境安全等4大防护,通过全链路扫描.问题关联及风险组织的方式保护企业软件供应链安全,降低企 ...

  2. Mac 复制文件名目录路径

    Mac快速复制文件路径 在Mac电脑上,我们经常需要复制文件的路径,其实,Mac系统提供了快速复制文件路径的方法.下面我们来详细介绍. 方法一:使用菜单栏 首先,打开Finder,然后选择你要复制路径 ...

  3. Kubernetes(K8S) Pod 介绍

    Pod 是 k8s 系统中可以创建和管理的最小单元, 是资源对象模型中由用户创建或部署的最小资源对象模型, 也是在 k8s 上运行容器化应用的资源对象, 其他的资源对象都是用来支撑或者扩展 Pod 对 ...

  4. Java SpringBoot FTP 上传下载文件

    POM 添加依赖 <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all< ...

  5. 忘了 iOS(iPad、IPhone) 设备上的「屏幕使用时间」密码怎么办?找回屏幕密码

    忘了 iOS(iPad.IPhone) 设备上的「屏幕使用时间」密码怎么办? 1. 用iTunes 进行备份[备份时一定要输入密码] 备份时C盘要有足够的空间 2. 下载 pinfinder.exe ...

  6. 【django-vue】七牛云上传视频 搜索接口 支付宝sdk二次封装 下单接口 前端支付页面 支付成功回调接口

    目录 上节回顾 课程详情接口 choice字段 今日内容 1 文件存储 1.1 七牛云上传文件 2 搜索导航栏 2.1 Header.vue 3 搜索接口 4 搜索页面 5 支付宝支付介绍 5.1 支 ...

  7. AliSSR 语音超分算法:让在线会议语音更明亮更自然

    超分让在线会议语音更明亮,在线会议已成为日常工作中较为普遍的沟通交流方式,接入会议的方式也呈现多样化,比如电脑入会.手机入会又或是电话入会. 雪雅.曜辰|作者 众所周知,高采样率且高带宽的音频信号富含 ...

  8. 为什么加了@Transactional注解,事务没有回滚?

    在昨天的<事务管理入门>一文发布之后,有读者联系说根据文章尝试,加了@Transactional注解之后,事务并没有回滚.经过一顿沟通排查之后,找到了原因,在此记录一下,给后面如果碰到类似 ...

  9. Codeforces Round #667 (Div. 3) A - D题题解

    Codeforces Round #667 (Div. 3) A - D Problem A - Yet Another Two Integers Problem https://codeforces ...

  10. VIM 入门手册, (VS Code)

    要想在VScode里使用Vim需要先行按照插件 安装 vim 插件 VS Code 中输入快捷键 shift + ctrl + x, 或直接打开 扩展安装导航 搜索 vim, 选择 Vim , 点击 ...