go waitgroup.done()异常处理_Go 异常处理
运行时恐慌 panic
这种程序异常叫做 panic,我们把它翻译成运行时恐慌。其中恐慌是由 panic 直译过来的,之所以加上运行时是因为这种异常只会在程序运行时的时候抛出来。
package mainimport "fmt"func main() { s := []int{0, 1, 2, 3, 4} fmt.Println(s[5])}//panic: runtime error: index out of range [5] with length 5////goroutine 1 [running]://main.main()///Users/zhangxuesong/gowork/src/gocore/gopanic/main.go:7 +0x1b//exit status 2
上面这个切片只有 5 个元素,而用下标 5 取第 6 个元素肯定不对的。Go 运行时系统执行到这一句时会抛出 panic,以提示我们索引越界了。如果我们没有在程序里添加任何保护措施,程序打印出 panic 详细信息后就会终止运行。
详情中 runtime error 表示这是一个 runtime 包抛出的 panic。其中包含了一个 runtime.Error 接口类型的值。runtime.Error 接口内嵌了 error 接口,并做了一点点扩展,runtime 包中有不少它的实现类型。
详情中 panic: 右面的内容正是这个 panic 包含的 runtime.Error 类型值的字符串表示形式。
此外,panic 详情中一般还会包含与它引发原因有关的 goroutine 的代码执行信息。正如详情中的 goroutine 1 [running]:,它表示有一个 ID 为 1 的 goroutine 在此 panic 被引发的时候正在运行。这里的 ID 并不重要,它只是 Go 运行时系统内部给予的一个编号,我们在程序中是无法获取和更改的。
main.main() 表示这个 goroutine 包装的 go 函数就是命令源码中的 main 函数,也就是说这里的 goroutine 正是主 goroutine。下面一行指出这个 goroutine 中的哪一行代码在此 panic 被引发时正在执行。这包含了此行代码所属的源码文件中的行数和文件所在的绝对路径。最后的 +0x1b 代表此行代码相对于其所属函数的入口程序计数偏移量。一般情况下用处不大。
最后,exit status 2 表示这个程序是以退出状态码 2 结束运行的。在大多数操作系统中,只要退出状态码不为 0,都意味着程序运行的非正常结束。在 Go 语言中,因 panic 导致程序结束运行的退出状态码一般都会是 2。
从 panic 被引发到程序终止的过程
某个函数中的某行代码有意或无意的引发了一个 panic。这时,初始的 panic 详情会被建立起来,并且该程序的控制权会从此行代码转移至调用其所属函数的那行代码上,也就是调用栈的上一级。
这也意味着,此行代码所属的函数的执行随即终止。紧接着,控制权并不会在此有片刻停留,它又会立即转移至再上一级的调用代码处。控制权如此一级一级的沿着调用栈的反方向传播至顶端,也就是我们编写的最外层函数那里。
这里的最外层函数指的是 go 函数,对于主 goroutine 来说就是 main 函数。但是控制权也不会停留在那里,而是被 Go 运行时系统回收。
随后,程序崩溃并终止运行,承载程序这次运行的进程也会随之死亡和消失。与此同时,在这个控制传播过程中,panic 详情会主键的积累和完善,并会在程序终止之前被打印出来。
panic 可能是我们在无意间引发的,如前文所属的索引越界。这类 panic 是真正的、在我们意料之外的程序异常。除此之外,我们还可以有意的引发 panic。
Go 语言内建函数 panic 是专门用于引发 panic 的。该函数使程序开发者可以在程序运行期间报告异常。注意,这与函数返回错误值的意义是完全不同的。当我们的函数返回一个非 nil 的错误值时,函数的调用放有权选择不处理,并且不处理的结果往往是不致命的。
这里的不致命是说不至于使程序无法提供任何功能或者直接崩溃并终止运行。
当一个 panic 发生时,如果我们不加任何保护措施,那么导致的后果可能是程序崩溃,这显然是致命的。
package mainimport ( "fmt")func main() { fmt.Println("Enter function main.") caller1() fmt.Println("Exit function main.")}func caller1() { fmt.Println("Enter function caller1.") caller2() fmt.Println("Exit function caller1.")}func caller2() { fmt.Println("Enter function caller2.") s1 := []int{0, 1, 2, 3, 4} e5 := s1[5] _ = e5 fmt.Println("Exit function caller2.")}
提示:panic 详情会在控制权传播的过程中,被主键的积累和完善,并且,控制权会一级一级的沿着调用栈反方向传播至顶端。
因此,在针对某个 goroutine 的代码执行信息中,调用栈底层的信息会先出现,然后是上一级的调用信息,以此类推,最后才是此调用栈顶端的信息。
Enter function main.Enter function caller1.Enter function caller2.panic: runtime error: index out of range [5] with length 5goroutine 1 [running]:main.caller2() /Users/zhangxuesong/gowork/src/gocore/gopanic/main1.go:22 +0x85main.caller1() /Users/zhangxuesong/gowork/src/gocore/gopanic/main1.go:15 +0x7emain.main() /Users/zhangxuesong/gowork/src/gocore/gopanic/main1.go:9 +0x7eexit status 2
深入地了解此过程,以及正确地解读 panic 详情应该是我们的必备技能,这在调试 Go 程序或者为 Go 程序排查错误的时候非常重要。
go waitgroup.done()异常处理_Go 异常处理相关推荐
- java future 异常处理_Java异常处理总结
转自:http://blog.51cto.com/lavasoft/18920 Java异常处理总结 异常处理是程序设计中一个非常重要的方面,也是程序设计的一大难点,从C开始,你也许已经知道如何用if ...
- php的异常处理,PHP异常处理Exception类
异常(Exception)用于在指定的错误发生时改变脚本的正常流程. 什么是异常? PHP 5 提供了一种新的面向对象的错误处理方法. 异常处理用于在指定的错误(异常)情况发生时改变脚本的正常流程.这 ...
- SpringMVC异常处理机制-异常处理两种方式
① 使用Spring MVC提供的简单异常处理器SimpleMappingExceptionResolver ② 实现Spring的异常处理接口HandlerExceptionResolver 自定义 ...
- SpringMVC异常处理机制-异常处理的思路
异常处理的思路 系统中异常包括两类:预期异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发.测试等手段减少运行时异常的发生. 系统的Dao.S ...
- SpringMVC异常处理之异常处理代码编写
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...
- PHP5异常处理,PHP5异常处理分析实例
PHP5异常处理分析实例 导语:PHP 5 添加了类似于其它语言的异常处理模块.下面的是百分网小编为大家搜集的用实例分析PHP5异常处理实例,希望对你能有所帮助. <?php /** * ■㈠P ...
- java异常处理 ppt_Java异常处理、多线程ppt课件
Java异常处理.多线程ppt课件 生产理论把企业仅仅抽象为一个生产函数.一种投入产出关系.一个追求利润最大化的"黑匣子 ",它没有讨论企业内部是如何配置资源的,企业是如何组织生产 ...
- python 异常处理_异常处理 — Python 3.7.9 文档
异常处理¶ The functions described in this chapter will let you handle and raise Python exceptions. It is ...
- java 开发者异常处理_Java异常处理和设计
本篇博客内容转自http://www.cnblogs.com/dolphin0520/p/3769804.html,内容供自己学习参考之用 在程序设计中,进行异常处理是非常关键和重要的一部分.一个程序 ...
最新文章
- 懒人必备 |通过爬虫 筛选以及查看CSDN 满足相应积分的资源列表 简单好用
- Java中创建对象的几种方式
- iOS点击推送消息跳到应用指定页面
- 优先级反转和解决方法
- Java Web应用程序:Oozie及其使用方式
- ArcGIS地理坐标系与投影坐标系
- ejb java_EJB继承与Java继承不同
- C语言中面向对象编程
- 画出计算机网络的一般组成,计算机网络习题(有答案).pdf
- 俄罗斯 IT 存储空间告急,未来 2 月或将耗尽?
- 广西龙脊梯田景区发生山体崩塌
- pytorch-迁移学习学习率trick
- paper reading:[renormalization]Semi-supervised Classification with Graph Convolutional Networks
- Haproxy+Nginx实现web负载均衡群集
- 中国五千年统一与分裂
- java面试宝典:留着慢慢看
- 流程审批类系统数据库结构怎么定义
- 设计网站中的精品,你可能需要它--第五期(Logo设计,助你提升效率)
- 百度文字识别OCR接口使用
- 一种突发事件的时滞动力学模型 2019-nCoV与参数辨识
热门文章
- 电信业务分类目录2019_2019年1月国内增值电信业务许可情况分析报告,市场区域发展不均衡...
- 利用向量叉积求三角形的面积(+STL:nth_element求第K大的数)
- 开放搜索查询分析服务架构解读
- 深入浅出讲解MSE Nacos 2.0新特性
- 搜索引擎新架构:与SQL不得不说的故事
- java getstringarray_Java AnnotationAttributes.getStringArray方法代碼示例
- python tkinter 循环显示文本_Python简易音乐播放器
- 《球球大作战》游戏优化之路(下)
- 一文教你玩转链上「动森」My Neighbor Alice
- J2ME手游开发日记