首页 > 其他分享 >go中异常处理流程

go中异常处理流程

时间:2023-11-18 11:12:32浏览次数:25  
标签:defer 协程 函数 异常 流程 Go go recover panic

在 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: 恋水无意
腾讯云开发者社区:孟斯特


标签:defer,协程,函数,异常,流程,Go,go,recover,panic
From: https://www.cnblogs.com/lianshuiwuyi/p/17840206.html

相关文章

  • 互联网医院牌照|湖南互联网医院牌照申请流程
    互联网医院牌照是由卫生健康行政部门颁布的,所有材料审核通过后,相关部门授予《医疗机构执业许可证》,取得牌照后才有开展互联网诊疗活动的资质,但开展线上问诊也需要向发证机关提出申请,下面小编就给大家讲解下互联网医院牌照申请流程。 一、向实体医院登记机关提交以下材料: 1、设置......
  • django如何将查询结果的栏位和数值自动遍历出来
    在Django中,MT003HModel.objects.all()返回的是一个QuerySet对象,你可以使用迭代器来遍历其中的每个对象,然后访问对象的属性来获取栏位和数值。以下是一个简单的示例代码,假设MT003HModel包含字段field1和field2:mt002_objects=MT003HModel.objects.all()formt002_obj......
  • django信号中的条件判断不符合时如何提示错误并返回
    在Django中,如果你在信号(Signal)处理函数中需要进行条件判断,如果条件不符合,你可以触发一个异常,并在视图或其他地方捕获这个异常,然后返回相应的错误提示。以下是一个简单的例子,演示如何在信号处理函数中进行条件判断并触发异常:#models.pyfromdjango.dbimportmodelsfromdjan......
  • django 信号判断是新增、修改还是删除
    在Django的信号处理器中,你可以使用一些方法来确定信号是关于新增(create)、修改(update)还是删除(delete)的。这通常涉及到检查created和instance参数的值。以下是一个例子,展示了如何在信号处理器中判断是新增、修改还是删除:fromdjango.db.models.signalsimportpost_save,pre......
  • django 信号第一个 raise ValidationError出现后,还会继续下一个if吗
    在你提供的代码片段中,如果第一个raiseValidationError触发,会抛出异常并停止执行当前函数或代码块。这是因为异常(Exception)会中断正常的代码流程,将控制权传递给调用堆栈中的第一个能够捕获该异常的地方。所以,如果v_lot_no为空,第一个raiseValidationError被触发后,后续的if......
  • Centos7.8 go1.18.3指定版本安装 完美运行Golang安装
    安装背景说明:公司已经有3台服务器安装了go1.18.3版本,这次又买了一台新服务器,由于线上推上去的功能,可能会导致用户出现异常,要做压力测试,所以要重建go环境。遇到问题:昨天下午自己下载了安装包,也是go1.18.3解析到了/usr/local目录也配置了环境/etc/profile 就是识别不到go ......
  • django 如何查询汇总的求和时避免没有数据导致的错误
    django如何查询汇总的求和时避免没有数据导致的错误在Django中,如果你希望对某个字段进行求和操作,并在没有数据时返回默认值,可以使用aggregate结合Coalesce函数。Coalesce函数用于返回参数中的第一个非空值,这样你可以在没有匹配项时设置默认值。以下是一个示例:fromdjan......
  • django 信号 新增和删除信的合用
    fromdjango.db.models.signalsimportpost_save,post_deletefromdjango.dispatchimportreceiverfromdjango.dbimporttransactionfrom.modelsimportMT002HModel@receiver(post_save,sender=MT002HModel)@receiver(post_delete,sender=MT002HModel)@transa......
  • MongoDB介绍
    一、简介1.1MongodbMongoDb是一个基于分布式文件存储的数据库,官方地址https://www.mongodb.com/1.2数据库数据库(DataBase)是按照数据结构来组织、存储和管理数据的应用程序。作用:数据库的主要作用就是管理数据,对数据进行增(c)、删(d)、改(u)、查(r)。核心概念:数据库(da......
  • Java常见八大异常(新手必看)
    ......