当前位置: 首页 > article >正文

Golang的panic和recover

原文链接,关注获取更多技术文章!

简述

我们都知道在Go语言中的异常处理是通过方法返回error,然后在调用方法处接收error并处理,这里的error通常是使用在业务异常的处理。

如果程序发生数组越界、空指针等异常就不会再通过error来处理,而是通过panic直接报错并终止程序和打印出堆栈信息。那么如何在程序发生panic的时候去处理这个异常而不是终止程序呢?这个时候就需要使用到recover,recover可以捕获到panic异常,并恢复程序的运行。

panic

  • 调用panic后立即终止执行当前函数的剩余代码,在当前goroutine中执行当前函数所有的defer
  • panic只会触发当前goroutine的defer

recover

  • 调用recover可以捕获panic的异常,并恢复程序的执行
  • recover只在defer延迟函数中调用才会生效

实战

示例1

我们首先在代码中直接使用recover捕获异常,并使用panic手动抛出一个异常,看看程序会怎么样

func main() {
	test()
	fmt.Println("main")
}

func test() {
	if err := recover(); err != nil {
		fmt.Println("recover: ", err)
	}
	panic("error")
}

运行上面的代码之后可以从输出看到在test函数中发生了panic,并且直接终止运行,导致main函数中的打印也没有生效,这是因为在前面的时候有讲到过,recover必须在defer延迟函数中调用才会生效。

panic: error                                                    
                                                                
goroutine 1 [running]:                                          
main.test()                                                     
        C:/Users/lee/GolandProjects/test/main.go:33 +0x30
main.main()                                                     
        C:/Users/lee/GolandProjects/test/main.go:24 +0x13

示例2

修改上面的代码,将recover放到defer延迟函数中调用:

func main() {
	test()
	fmt.Println("main")
}

func test() {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println("recover: ", err)
		}
	}()
	panic("error")
}

这个时候我们再次运行代码,可以看到虽然在test函数中发生了panic,但是程序并没有终止运行,而是被defer中的recover捕获到了异常并恢复运行,同时main函数中的print也正常打印。

recover:  error
main

示例3

上面示例2中将recover是放到defer的函数中调用,那么如果在defer后面直接调用recover会生效吗?使用下面代码进行测试。

func main() {
	test()
	fmt.Println("main")
}

func test() {
	defer recover()
	panic("error")
}

运行上面的代码之后发现在defer后面直接调用recover是无效的,程序照样会发生异常并终止运行,所以**recover必须是在defer的延迟函数中调用才会生效。**示例2中是匿名延迟函数,如果使用具名延迟函数同样有效。

panic: error

goroutine 1 [running]:
main.test()
        C:/Users/lee/GolandProjects/test/main.go:30 +0x58
main.main()
        C:/Users/lee/GolandProjects/test/main.go:24 +0x13

示例4

上面说到过recover必须在defer的延迟函数中调用,那下面的代码可以生效吗?

func main() {
	test()
	fmt.Println("main")
}

func test() {
	defer func() {
		defer recover()
	}()
	panic("error")
}

运行上面的代码可以看到recover是生效的,recover函数被一个延迟函数调用,且recover函数本身作为一个延迟函数,这个情况下也是可以正常捕获panic异常的,程序运行如下:

main

公众号:CodeJR,关注获取更多技术文章!


http://www.kler.cn/a/297065.html

相关文章:

  • 哈希表,算法
  • 软件工程知识点总结(3):需求分析(二)——分析模型建模
  • 无人机之动力系统篇
  • Python Flask_APScheduler定时任务的正确(最佳)使用
  • RuoYi-Vue若依框架-系统监控内定时任务的使用
  • 深圳市2025年重大项目计划开放申报,9月23日申报截止
  • 以实时,见未来——DolphinDB 2024 年度峰会圆满举办
  • linux定时监听ssh服务是否启动-------麒麟操作系统永久关闭swap
  • 【springsecurity】使用PasswordEncoder加密用户密码
  • llvm后端之函数栈帧的创建与销毁
  • 线性代数 第七讲 二次型_标准型_规范型_坐标变换_合同_正定二次型详细讲解_重难点题型总结
  • ARM汇编
  • 记录:uniapp直播的弹幕的样式修改与发送弹幕会自动滚动到底部两个技巧
  • HTML 超链接
  • 量化投资策略与技术学习PART9:量化选股之筹码选股
  • 验证码识别之点选验证码识别——绪论
  • 资深研发的心愿:PostgreSQL未来若能加入这些功能,将更臻完善
  • 周报 | 24.9.2-24.9.8文章汇总
  • flutter之常用数据类型
  • 佰朔资本:沪指跌0.23%,金融板块集体上扬,半导体等板块下挫