【GoLang】panic defer recover 深入理解
唉,只能说C程序员可以接受go的错误设计,相比java来说这个设计真的很差劲!
我认为知乎上说的比较中肯的:

1. The key lesson, however, is that errors are values and the full power of the Go programming language is available for processing them.
2. Use the language to simplify your error handling.
But remember: Whatever you do, always check your errors!
Golang这么时尚的语言是没有类似try..catch 这种异常处理机制,而是使用 panic 和 recover处理异常. 其实相当于python的raise。
golang的异常处理组合 panic,defer,recover,跟java中的try catch finially是类似的。 但是从语言的用户体验来说,不怎么好。 但考虑到golang的场景基本是系统高性能层面的,这种精准错误处理应该减少那种后遗症bug。
该文章写的有些乱,欢迎来喷 ! 另外文章后续不断更新中,请到原文地址查看更新。
使用panic抛出异常,抛出异常后将立即停止当前函数的执行并运行所有被defer的函数,然后将panic抛向上一层,直至程序carsh。但是也可以使用被defer的recover函数来捕获异常阻止程序的崩溃,recover只有被defer后才是有意义的。
必须注意:
1. defer 需要放在 panic 之前定义,另外recover只有在 defer 调用的函数中才有效。
2. recover处理异常后,逻辑并不会恢复到 panic 那个点去,函数跑到 defer 之后的那个点.
3. 多个 defer 会形成 defer 栈,后定义的 defer 语句会被最先调用
panic (主动爆出异常) 与 recover (收集异常)
recover 用来对panic的异常进行捕获. panic 用于向上传递异常,执行顺序是在 defer 之后。
我们举个含有异常的例子:
Python
|
1
2
3
4
5
6
7
8
9
10
11
12
|
#xiaorui.cc
func f() {
for {
fmt.Println("1")
a := []string{"a","b"}
fmt.Println(a[3]) // 这里slice越界异常了
/*panic("bug")*/
fmt.Println("4")
time.Sleep(1 * time.Second)
}
}
|
如果你不把这个异常panic recover处理的化,那么就会发生下面的情况.
Python
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#xiaorui.cc
1
panic: runtime error: index out of range
goroutine 1 [running]:
panic(0xda9c0, 0x8201c8090)
/usr/local/go/src/runtime/panic.go:464 +0x3e6
main.f()
/Users/ruifengyun/gg.go:23 +0x33b
main.main()
/Users/ruifengyun/gg.go:16 +0x14
exit status 2
|
下面是处理panic的例子.
Python
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
package main
import (
"fmt"
"time"
)
func main() {
defer func() { //必须要先声明defer,否则不能捕获到panic异常
fmt.Println("2")
if err := recover(); err != nil {
fmt.Println(err) //这里的err其实就是panic传入的内容,bug
}
fmt.Println("3")
}()
f()
}
func f() {
for {
fmt.Println("1")
panic("bug")
fmt.Println("4") //不会运行的.
time.Sleep(1 * time.Second)
}
}
|
那么上面代码的运行结果是:
Python
|
1
2
3
4
5
|
1
2
bug
3
|
上面go代码实例中,异常是我们通过panic方法主动抛出来的,但如果真的就出现了未知的异常咋办?
上面go代码运行结果是:
Python
|
1
2
3
4
5
6
|
1
xiaorui.cc start
runtime error: index out of range
xiaorui.cc end
end
|
先前没在意defer recover panic的注意事项,结果各种问题出现了。 不知道go以后会不会有try catch异常模式, 很是期待…
END.
参考资料:
http://xiaorui.cc/2016/03/09/%E5%85%B3%E4%BA%8Egolang%E7%9A%84panic-recover%E5%BC%82%E5%B8%B8%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/
http://www.linuxidc.com/Linux/2013-04/83105.htm
http://blog.csdn.net/wuwenxiang91322/article/details/9042503
https://www.zhihu.com/question/27158146
【GoLang】panic defer recover 深入理解的更多相关文章
- golang panic and recover
panic 是一个内置函数,当一个函数 F 调用 panic,F 的执行就会停止,F 中 deferred 函数调用会被执行,然后 F 返回控制到它的调用者.这个过程会沿着调用栈执行下去,直到当前 g ...
- 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有没有一种异常 ...
- 理解Defer、Panic和Recover
刚开始的时候理解如何使用Defer和Recover有一点怪异,尤其是使用了try/catch块的时候.有一种模式可以在Go中实现和try/catch语句块一样的效果.不过之前你需要先领会Defer.P ...
- GO_05_2:Golang 中 panic、recover、defer 的用法
函数 defer 1. 它的执行方式类似其他语言中的折构函数,在函数体执行结束后按照调用顺序的 相反顺序 逐个执行 2. 即使函数发生 严重错误 也会被执行,类似于 java 中 try{...} ...
- Golang 入门系列(十四)defer, panic和recover用法
以前讲过golang 的基本语法.但是,只是讲了一些基础的语法,感兴趣的可以看看以前的文章,https://www.cnblogs.com/zhangweizhong/category/1275863 ...
- Golang错误处理函数defer、panic、recover、errors.New介绍
在默认情况下,当发生错误(panic)后,程序就会终止运行 如果发生错误后,可以捕获错误,并通知管理人员(邮件或者短信),程序还可以继续运行,这当然无可厚非 errors.New("错误信息 ...
- Golang的panic和recover
panic 关键字panic的作用是制造一次宕机,宕机就代表程序运行终止,但是已经“生效”的延迟函数仍会执行(即已经压入栈的defer延迟函数,panic之前的). 为什么要制造宕机呢?是因为宕机不容 ...
- Golang异常处理-panic与recover
Golang异常处理-panic与recover 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在程序设计中,容错是相当重要的一部分工作,在 Go中它是通过错误处理来实现的,err ...
随机推荐
- 一个有趣的模拟光照的shader
一个有趣的模拟光照的shader(类似法线贴图) http://www.cnblogs.com/flytrace/p/3395911.html ----- 可否用于需UI中需要加灯的模型.
- centos 7.0 ssh 登陆
CentOS 7.0 最小化安装 默认连接 默认端口是22 安装完查看IP 命令 ip addr ip: 192.168.1.103 自己家里练习的机子 都没改配置了 使用putty 远程连接 下载页 ...
- Python之迭代器和生成器
Python 迭代器和生成器 迭代器 Python中的迭代器为类序列对象(sequence-like objects)提供了一个类序列的接口,迭代器不仅可以对序列对象(string.list.tupl ...
- Redis-cluster集群【第三篇】:redis主从
Redis主从复制原理: 通过把这个RDB文件或AOF文件传给slave服务器,slave服务器重新加载RDB文件,来实现复制的功能! 复制的话:主服务器可以有多个从服务器!!! 不仅这样从服务器还 ...
- Python之路【第三篇】:Python基础(二)
函数的理解 面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 函数作用是你的程序有良好的扩展性.复用性. 同样的功能要是用3次以上的话就建议 ...
- Yii2创建多界面主题(Theme)
Yii2界面主题上的设计总体上和Yii1.x保持一致,区别在于两个地方: 1. 由于Yii2引入了独立的视图(View)类,因此界面主题(Theme)也交由视图来管理: 2. 视图文件和Web资源在目 ...
- JavaScript 中 的prototype和__proto__
1.prototype是函数的一个属性(每个函数都有一个prototype属性),这个属性是一个指针,指向一个对象.它是显示修改对象的原型的属性. 2.__proto__是一个对象拥有的内置属性(请注 ...
- Win7电脑无法启用无线连接或无线连不上网
1. 上不去网,看是否是无线网卡禁止. 2. 打开控制面板--网络和Internet--查看网络状态和任务--更改网络适配器 3. 4.若启用后无线网络连接仍为灰色,继续往下看 5.点击开始,找到运行 ...
- [bug] 未能加载文件或程序集“SIPEPS, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”或它的某一个依赖项。系统找不到指定的文件。
摘要 在弄ucma的web项目中总会出现这个问题.尝试了很多方法,最后这样解决了. 解决方案 使web以64位的方式运行.
- 如何才能实现在点击链接时直接在网页中打开word文档,但不提示保存
一般要直接打开需要客户端 1.客户端有word支持 2.客户端浏览器的版本与设置 可寻找一下相关的控件或中间件,我的意见是看能否变通一下,把word转成HTML或PDF再展示给用户.(若用户不需要编辑 ...