Golang 的异常处理机制

1. 什么是异常处理

程序在执行过程中有可能出现异常状态,比如获取一个不再有效指针指向的内容、除零等。

一般语言都提供了异常处理机制来应对这些情形,例如 Java 的 // 机制(https://docs.oracle.com/javase/tutorial/essential/exceptions/catch.html)、

Python 的 /// 机制(https://docs.python.org/3/tutorial/errors.html)等。

2. Go 语言中的异常处理机制

Go 语言中使用的是 // 机制来处理异常。Go 语言官方博客的《Defer, Panic, and Recover》讲述了这个机制的具体应用方式。

还有一些其他教程对这个机制的使用方法、适用场景进行了进一步阐述:

The Right Places To Call The recover Function:https://go101.org/article/panic-and-recover-more.html ,几种使用 恢复 Go 语言中 的适用场景

7.异常处理:https://www.kancloud.cn/liupengjie/go/578555 ,看云发布的 Go 语言教程中涉及到异常处理的章节,里面涉及到很多使用示例细节

如果搜索 “golang 异常处理”,类似的教程有很多。里面的核心思想大体就是:用 + 处理一个 , 结构要在 触发之前被定义而且 要直接在在 结构定义的函数中被调用(而不是被直接调用或者在函数内部的其他函数中被调用)。

3. 语法糖的部分原理

在讲述 机制的文章中,都会提到一个函数中多个 结构执行的顺序和定义顺序是相反的,即后定义的 结构总是先被执行。为什么会出现这样的情况?例如下面的代码:

调用 输出为:

常见的函数调用流程为:

将函数使用的参数压入栈

执行函数指令

函数执行结束返回到调用点

如果 相关的代码也是这么执行的话,那么为什么不是: 入栈 - 执行 - 返回 - 入栈 - 执行 - 返回 这个顺序呢?

按照这个顺序执行,调用 输出应该是 在 前面符合预期。是不是 Go 语言中执行 时采用了特殊的处理流程?

是,也不是。

太阳底下无新鲜事, 不过是一个语法糖,用来对一个函数 进行包装。

创建一个延迟调用的函数,其参数为 (延迟调用的函数的参数占用的字节数量)和 (被延迟调用的函数本身)。

当 Go 程序的编译器遇到 ,会将这条语句翻译为一条 和一条 。

其中 把被调用的函数及其参数挂载在 goroutine (Go 中的并发单元,协程)结构的一个链表上;

从链表上取下一个挂载的被延迟执行的函数,执行它。

如何使用技巧绕过 关键字,模拟类似效果?

可以使用 方法来把 Go 语言运行时的一些关键函数导出,从而进行某些不常见的操作。

这段代码会输出:

当然,如果是使用 关键字,Go 语言的编译器会选择合适的位置插入 语句,而不是像上述代码中一样手动放在结束位置处。

4. 生效位置的设计原因推测

言归正传, 发生后,会根据函数调用顺序逐层上报,直到最后一层被抛出到系统导致崩溃或者被 机制处理。

那么如果被 处理,这个过程是怎么生效的?

很多教程中都提到 一定要在 声明的函数里面(既不是这个函数本身也不能是函数里面的其他函数里面)才能正确处理当前的 。

为什么呢?

先不考虑实现,先从理念上分析一下。

直接作用于 :无法根据 的返回值来进行不同类型的 处理

在被 作用的函数内部的函数 中使用 :如果 是一个第三方库的函数,无法保证其中没有未知的 意外处理了系统中的 。

因此事实上也只能通过这样的约束来使这个异常处理机制看上去直观易处理一些。当然通过对 Go 编译器进行修改,还是有办法使得上面三种情况下 都可以中断 向上层传递过程的。

此外,由于被 处理的函数被挂载在 goroutine 结构的一个链表上,因此当 发生时,可以直接从这个链表上取下被延迟执行的函数一个个执行。

这也是 要放在 中的原因,因为这些函数是肯定可以执行到的。

5. 总结

不能说 Go 中这个异常处理机制有多高明,基本上属于现代语言标配。了解更多背后的原理,在使用时可以更坚定一些。

此外,最近看到一本书《最好的告别》(https://book.douban.com/subject/26576861/)。

豆瓣上的介绍:

当独立、自助的生活不能再维持时,我们该怎么办?在生命临近终点的时刻,我们该和医生谈些什么?应该如何优雅地跨越生命的终点?对于这些问题,大多数人缺少清晰的观念,而只是把命运交由医学、技术和陌生人来掌控。影响世界的医生阿图•葛文德结合其多年的外科医生经验与流畅的文笔,讲述了一个个伤感而发人深省的故事,对在21世纪变老意味着什么进行了清醒、深入的探索。

/ 这些关键字让我们可以控制函数退出时的行为,但是我们自身呢?也许考虑这些问题可以让我们自身活得有意义一些。

推荐大家看一下。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180824G1X60O00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券