panic

  关键字panic的作用是制造一次宕机,宕机就代表程序运行终止,但是已经“生效”的延迟函数仍会执行(即已经压入栈的defer延迟函数,panic之前的)。

  为什么要制造宕机呢?是因为宕机不容易遇到?还是因为程序有错就是直接报错,都没有执行,哪来的宕机?

  Go程序设计语言中这样提到:如果碰到“不可能发生的”的状况,宕机是最好的处理方式。这个“不可能发生的”状况很难理解,不过可以这样想:一个机器人的能源供应,可能依靠太阳能,可能依靠电能,但是如果靠吃饭解决,那么这肯定就不可思议了,这时候就应该触发一次宕机。

关于panic,下面是一个例子:

  1. package main
  2. import "fmt"
  3. func main(){
  4. defer func(){
  5. fmt.Println("aaaaaa")
  6. }()
  7. fmt.Println("bbbbbb")
  8. fmt.Println("cccccc")
  9. panic("hahahaha")
  10. fmt.Println("ddddd")
  11. defer func(){
  12. fmt.Println("eeeeeeee")
  13. }()
  14. }

  首先顺序执行,会先将第一个defer延迟函数“入栈”(这里称为入栈是为了便于理解),然后输出“bbbbbbb",”cccccccc”,此时使用panic来触发一次宕机,panic接受一个任意类型的参数,会将该字符串输出,用作提示信息,之后的代码不再执行,所以后面的dddddd不会输出,而且第二个defer延迟函数也不会“入栈”,因为panic之后的代码不会继续执行,程序现在只会运行已经“入栈”的defer延迟函数,输出aaaaaa,在最后,会输出此次触发宕机的一些信息,所以执行结果如下:

  1. bbbbbb
  2. cccccc
  3. aaaaaa
  4. panic: hahahaha
  5.  
  6. goroutine 1 [running]:
  7. main.main()
  8. /Users/root/Desktop/test.go:9 +0xf1
  9. 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截获,于是错误信息就不会显示,转而进行下一步操作。

下面是一个简单的示例:

  1. package main
  2. import "fmt"
  3. func main() {
  4. defer func() {
  5. if info := recover(); info != nil {
  6. fmt.Println("触发了宕机", info)
  7. } else {
  8. fmt.Println("程序正常退出")
  9. }
  10. }()
  11. fmt.Println("bbbbbb")
  12. fmt.Println("cccccc")
  13. panic("fatal error")
  14. fmt.Println("ddddd")
  15. defer func() {
  16. fmt.Println("eeeeeeee")
  17. }()
  18. }

  运行结果如下:

  1. bbbbbb
  2. cccccc
  3. 触发了宕机 fatal error

  

Golang的panic和recover的更多相关文章

  1. Golang异常处理-panic与recover

    Golang异常处理-panic与recover 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在程序设计中,容错是相当重要的一部分工作,在 Go中它是通过错误处理来实现的,err ...

  2. 【GoLang】panic defer recover 深入理解

    唉,只能说C程序员可以接受go的错误设计,相比java来说这个设计真的很差劲! 我认为知乎上说的比较中肯的: 1. The key lesson, however, is that errors ar ...

  3. GO_05_2:Golang 中 panic、recover、defer 的用法

     函数 defer 1. 它的执行方式类似其他语言中的折构函数,在函数体执行结束后按照调用顺序的 相反顺序 逐个执行 2. 即使函数发生 严重错误 也会被执行,类似于 java 中 try{...} ...

  4. golang之panic,recover,defer

    defer,recover: 运行时恐慌一旦被引发,就会向调用方传播直至程序崩溃. recover内建函数用于“拦截”运行时恐慌,可以使当前的程序从恐慌状态中恢复并重新获得流程控制权. recover ...

  5. GOLANG错误处理最佳方案errors wrap, Defer, Panic, and Recover

    Simple error handling primitives:        https://github.com/pkg/errors Defer, Panic, and Recover:    ...

  6. Golang 高效实践之defer、panic、recover实践

    前言 我们知道Golang处理异常是用error返回的方式,然后调用方根据error的值走不同的处理逻辑.但是,如果程序触发其他的严重异常,比如说数组越界,程序就要直接崩溃.Golang有没有一种异常 ...

  7. Golang错误处理函数defer、panic、recover、errors.New介绍

    在默认情况下,当发生错误(panic)后,程序就会终止运行 如果发生错误后,可以捕获错误,并通知管理人员(邮件或者短信),程序还可以继续运行,这当然无可厚非 errors.New("错误信息 ...

  8. golang错误处理机制:panic与recover

    原文地址:http://www.niu12.com/article/14 panic知识点 package main import ( "fmt" "github.com ...

  9. panic和recover的使用规则

    转自个人博客 chinazt.cc 在上一节中,我们介绍了defer的使用. 这一节中,我们温习一下panic和recover的使用规则. 在golang当中不存在tye ... catch 异常处理 ...

随机推荐

  1. myeclipse中配置spring xml自己主动提示

    版权声明: https://blog.csdn.net/zdp072/article/details/24582173 这是一篇分享技巧的文章:myeclipse中配置spring xml自己主动提示 ...

  2. javascript中apply()和call()方法及区别

    call()和apply()方法 1.方法定义 call方法: 语法:obj.call(thisObj, arg1, arg2, ...); 定义:调用一个对象的一个方法,以另一个对象替换当前对象. ...

  3. map && multimap

    map map 的意思是映射.用法一般是     map<char, int>mp 按照我的理解,map 类似于一个高级的数组.前面的数据类型 char 相当于下脚标,而数组元素的值就对应 ...

  4. 单节点etcd配置

    $ cat /etc/etcd/etcd.conf ETCD_DATA_DIR="/var/lib/etcd/default.etcd" #监听URL,用于与其他节点通讯 ETCD ...

  5. Arduino 433 自定义发射

    /* This is a minimal sketch without using the library at all but only works for the 10 pole dip swit ...

  6. 使用 ps、strace、lsof 进行 Linux 进程 trouble-shooting

      linux_observability_tools 介绍 在Linux 下进行进程的排错,有很多方法.比如,修改源代码,print出一些关键的信息,如果代码是Python 的话,可以使用trace ...

  7. Redis学习笔记--Redis数据过期策略详解==转

    本文对Redis的过期机制简单的讲解一下 讲解之前我们先抛出一个问题,我们知道很多时候服务器经常会用到redis作为缓存,有很多数据都是临时缓存一下,可能用过之后很久都不会再用到了(比如暂存sessi ...

  8. python对word的操作

    from docx import Document from docx.shared import Inches document = Document() document.add_heading( ...

  9. python链家网高并发异步爬虫asyncio+aiohttp+aiomysql异步存入数据

    python链家网二手房异步IO爬虫,使用asyncio.aiohttp和aiomysql 很多小伙伴初学python时都会学习到爬虫,刚入门时会使用requests.urllib这些同步的库进行单线 ...

  10. PAT A1121 Damn Single (25 分)——set遍历

    "Damn Single (单身狗)" is the Chinese nickname for someone who is being single. You are suppo ...