设为首页 收藏本站
查看: 1089|回复: 0

[经验分享] 【GoLang】panic defer recover 深入理解

[复制链接]

尚未签到

发表于 2018-9-20 10:10:43 | 显示全部楼层 |阅读模式
  唉,只能说C程序员可以接受go的错误设计,相比java来说这个设计真的很差劲!
  我认为知乎上说的比较中肯的:
DSC0000.png

  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。
  该文章写的有些乱,欢迎来喷 ! 另外文章后续不断更新中,请到原文地址查看更新。
  http://xiaorui.cc/?p=2909
  使用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 123456789101112 #xiaorui.ccfunc 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 12345678910111213 #xiaorui.cc1panic: runtime error: index out of range goroutine 1 [running]:panic(0xda9c0, 0x8201c8090)    /usr/local/go/src/runtime/panic.go:464 +0x3e6main.f()    /Users/ruifengyun/gg.go:23 +0x33bmain.main()    /Users/ruifengyun/gg.go:16 +0x14exit status 2  下面是处理panic的例子.
Python 123456789101112131415161718192021222324252627 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 12345 12bug3  上面go代码实例中,异常是我们通过panic方法主动抛出来的,但如果真的就出现了未知的异常咋办?
我们可以看到出现的异常会走到defer这一步,defer这里可以打印具体的异常信息,defer运行完之后不能回到原点,控制权会被扔到该函数的外层,也就是调用这个函数的层,对应上面的代码也就是main()函数。  上面go代码运行结果是:
Python 123456 1xiaorui.cc startruntime error: index out of rangexiaorui.cc endend  先前没在意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


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-598711-1-1.html 上篇帖子: 在Golang中实现有无限容量的同步Queue 下篇帖子: golang闭包里的坑
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表