Golang的panic和recover
panic
关键字panic的作用是制造一次宕机,宕机就代表程序运行终止,但是已经“生效”的延迟函数仍会执行(即已经压入栈的defer延迟函数,panic之前的)。
为什么要制造宕机呢?是因为宕机不容易遇到?还是因为程序有错就是直接报错,都没有执行,哪来的宕机?
Go程序设计语言中这样提到:如果碰到“不可能发生的”的状况,宕机是最好的处理方式。这个“不可能发生的”状况很难理解,不过可以这样想:一个机器人的能源供应,可能依靠太阳能,可能依靠电能,但是如果靠吃饭解决,那么这肯定就不可思议了,这时候就应该触发一次宕机。
关于panic,下面是一个例子:
package main
import "fmt"
func main(){
defer func(){
fmt.Println("aaaaaa")
}()
fmt.Println("bbbbbb")
fmt.Println("cccccc")
panic("hahahaha")
fmt.Println("ddddd")
defer func(){
fmt.Println("eeeeeeee")
}()
}
首先顺序执行,会先将第一个defer延迟函数“入栈”(这里称为入栈是为了便于理解),然后输出“bbbbbbb",”cccccccc”,此时使用panic来触发一次宕机,panic接受一个任意类型的参数,会将该字符串输出,用作提示信息,之后的代码不再执行,所以后面的dddddd不会输出,而且第二个defer延迟函数也不会“入栈”,因为panic之后的代码不会继续执行,程序现在只会运行已经“入栈”的defer延迟函数,输出aaaaaa,在最后,会输出此次触发宕机的一些信息,所以执行结果如下:
bbbbbb
cccccc
aaaaaa
panic: hahahaha goroutine 1 [running]:
main.main()
/Users/root/Desktop/test.go:9 +0xf1
exit status 2
为什么不执行panic后面的defer,其实这个很好理解,比如,有两次读文件操作,那么每一次读文件之后都是用defer关闭文件,如果第一次读文件就引发了panic异常,而第二次读文件操作还没开始,也就是说还没有打开文件,那么调用第二个defer来关闭第二个文件,有意义吗?应该是只关闭第一个打开的文件,对吧?也就是调用第一个defer。
recover
recover从英文的意思上就知道是恢复,那么这个恢复是恢复什么呢?是恢复运行状态,继续运行?还是恢复到宕机之前?
其实,recover在英文中指的是受伤的愈合,防止伤口进一步感染。伤是愈合了,但是伤了始终是伤了,愈合只不过是事后处理而已。所以golang中的recover也只是发生宕机之后的后事处理。
所以这里的recover只是用来接收panic触发的宕机,如果panic触发宕机,传给panic的任意类型的参数,recover会接收到这个参数,recover获取到值之后才知道发生了宕机;相反,如果程序中的recover没有获取到值,则代表没有发生宕机,那么recover的值就为nil,通过这个可以来进一步处理后事。
前面已经提到panic的时候,已经说了,一旦发生宕机,其后的代码是不会执行的,但是会调用位于panic代码所在的哪一行之前的defer延迟函数,所以说这个特性就决定recover应该用在defer函数中,否则一旦发生宕机,除了defer延迟函数中的语句还能执行外,其他的语句都是不能执行的。
如果触发宕机,panic的错误信息会显示,如果有recover时,则信息会被recover截获,于是错误信息就不会显示,转而进行下一步操作。
下面是一个简单的示例:
package main
import "fmt"
func main() {
defer func() {
if info := recover(); info != nil {
fmt.Println("触发了宕机", info)
} else {
fmt.Println("程序正常退出")
}
}()
fmt.Println("bbbbbb")
fmt.Println("cccccc")
panic("fatal error")
fmt.Println("ddddd")
defer func() {
fmt.Println("eeeeeeee")
}()
}
运行结果如下:
bbbbbb
cccccc
触发了宕机 fatal error
Golang的panic和recover的更多相关文章
- Golang异常处理-panic与recover
Golang异常处理-panic与recover 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在程序设计中,容错是相当重要的一部分工作,在 Go中它是通过错误处理来实现的,err ...
- 【GoLang】panic defer recover 深入理解
唉,只能说C程序员可以接受go的错误设计,相比java来说这个设计真的很差劲! 我认为知乎上说的比较中肯的: 1. The key lesson, however, is that errors ar ...
- GO_05_2:Golang 中 panic、recover、defer 的用法
函数 defer 1. 它的执行方式类似其他语言中的折构函数,在函数体执行结束后按照调用顺序的 相反顺序 逐个执行 2. 即使函数发生 严重错误 也会被执行,类似于 java 中 try{...} ...
- golang之panic,recover,defer
defer,recover: 运行时恐慌一旦被引发,就会向调用方传播直至程序崩溃. recover内建函数用于“拦截”运行时恐慌,可以使当前的程序从恐慌状态中恢复并重新获得流程控制权. recover ...
- GOLANG错误处理最佳方案errors wrap, Defer, Panic, and Recover
Simple error handling primitives: https://github.com/pkg/errors Defer, Panic, and Recover: ...
- Golang 高效实践之defer、panic、recover实践
前言 我们知道Golang处理异常是用error返回的方式,然后调用方根据error的值走不同的处理逻辑.但是,如果程序触发其他的严重异常,比如说数组越界,程序就要直接崩溃.Golang有没有一种异常 ...
- Golang错误处理函数defer、panic、recover、errors.New介绍
在默认情况下,当发生错误(panic)后,程序就会终止运行 如果发生错误后,可以捕获错误,并通知管理人员(邮件或者短信),程序还可以继续运行,这当然无可厚非 errors.New("错误信息 ...
- golang错误处理机制:panic与recover
原文地址:http://www.niu12.com/article/14 panic知识点 package main import ( "fmt" "github.com ...
- panic和recover的使用规则
转自个人博客 chinazt.cc 在上一节中,我们介绍了defer的使用. 这一节中,我们温习一下panic和recover的使用规则. 在golang当中不存在tye ... catch 异常处理 ...
随机推荐
- HTML和CSS实现左侧固定宽度右侧内容可滚动
在做移动端页面的时候,经常会碰到一个div中分左右两个div,左侧div固定宽度或百分比,右侧div中内容左右溢出,需要左右滑动才可以浏览到全部内容,为此写了一个demo. 处理这个问题的核心关键点是 ...
- 面试被问http协议?这篇文章足够覆盖所有相关问题!
http使用面向连接的TCP作为传输层协议.http本身无连接. 请求报文 CRLF是回车换行 方法为GET的请求报文 方法为POST的请求报文 方法 OPTIONS:这个方法 ...
- Installation Oracle11gR2 RAC---常见报错处理
第六章.报错处理 6.1 root.sh脚本执行失败处理 安装grid时,执行rootsh脚本报错如下: Adding Clusterware entries to inittab USM drive ...
- P2347 砝码称重 (01背包)
题目描述 设有 1g1g1g . 2g2g2g . 3g3g3g . 5g5g5g . 10g10g10g . 20g20g20g 的砝码各若干枚(其总重 ≤1000 \le 1000≤1000 ), ...
- centos断网调试
保存命令 按ESC键 跳到命令模式,然后: :w 保存文件但不退出vi:w file 将修改另外保存到file中,不退出vi:w! 强制保存,不推出vi:wq 保存文件并退出vi:wq! 强制保存文件 ...
- oracle批量插入数据(测试)
做数据库开发或管理的人经常要创建大量的测试数据,动不动就需要上万条,如果一条一条的录入,那会浪费大量的时间,本文介绍了Oracle中如何通过一条 SQL快速生成大量的测试数据的方法.产生测试数据的SQ ...
- [转]系统架构演变--集中式架构-垂直拆分-分布式服务-SOA(服务治理)-微服务
一.系统架构演变 1.1. 集中式架构 当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本.此时,用于简化增删改查工作量的数据访问框架(ORM)是影响项目开发的关键. 存在的 ...
- vue2.0 broadcast和dispatch的理解
阅读目录 vue2 broadcast和dispatch的理解 回到顶部 vue2 broadcast和dispatch的理解 /* broadcast 事件广播 @param {componentN ...
- python中#!/usr/bin/python与#!/usr/bin/env python的区别
目的是在运行python脚本的时候告诉操作系统我们要用python解释器去运行py脚本 所以我们在第一句往往会写如下两句中的其中一句: #!/usr/bin/python 或 >#!/usr/b ...
- security相关链接整理
token令牌 ssl协议 https协议 对称加密与非对称加密 认识ASP.NET Windows身份认证