Go语言核心36讲
郝林
《Go并发编程实战》作者,前轻松筹大数据负责人
立即订阅
24139 人已学习
课程目录
已完结 54 讲
0/4登录后,你可以任选4讲全文学习。
开篇词+学习路线 (3讲)
开篇词 | 跟着学,你也能成为Go语言高手
免费
预习篇 | 写给0基础入门的Go语言学习者
50 | 学习专栏的正确姿势
模块一:Go语言基础知识 (6讲)
01 | 工作区和GOPATH
02 | 命令源码文件
03 | 库源码文件
04 | 程序实体的那些事儿(上)
05 | 程序实体的那些事儿(中)
06 | 程序实体的那些事儿 (下)
模块二:Go语言进阶技术 (16讲)
07 | 数组和切片
08 | container包中的那些容器
09 | 字典的操作和约束
10 | 通道的基本操作
11 | 通道的高级玩法
12 | 使用函数的正确姿势
13 | 结构体及其方法的使用法门
14 | 接口类型的合理运用
15 | 关于指针的有限操作
16 | go语句及其执行规则(上)
17 | go语句及其执行规则(下)
18 | if语句、for语句和switch语句
19 | 错误处理(上)
20 | 错误处理 (下)
21 | panic函数、recover函数以及defer语句 (上)
22 | panic函数、recover函数以及defer语句(下)
模块三:Go语言实战与应用 (27讲)
23 | 测试的基本规则和流程 (上)
24 | 测试的基本规则和流程(下)
25 | 更多的测试手法
26 | sync.Mutex与sync.RWMutex
27 | 条件变量sync.Cond (上)
28 | 条件变量sync.Cond (下)
29 | 原子操作(上)
30 | 原子操作(下)
31 | sync.WaitGroup和sync.Once
32 | context.Context类型
33 | 临时对象池sync.Pool
34 | 并发安全字典sync.Map (上)
35 | 并发安全字典sync.Map (下)
36 | unicode与字符编码
37 | strings包与字符串操作
38 | bytes包与字节串操作(上)
39 | bytes包与字节串操作(下)
40 | io包中的接口和工具 (上)
41 | io包中的接口和工具 (下)
42 | bufio包中的数据类型 (上)
43 | bufio包中的数据类型(下)
44 | 使用os包中的API (上)
45 | 使用os包中的API (下)
46 | 访问网络服务
47 | 基于HTTP协议的网络服务
48 | 程序性能分析基础(上)
49 | 程序性能分析基础(下)
尾声与思考题答案 (2讲)
尾声 | 愿你披荆斩棘,所向无敌
新年彩蛋 | 完整版思考题答案
Go语言核心36讲
登录|注册

21 | panic函数、recover函数以及defer语句 (上)

郝林 2018-09-28
我在上两篇文章中,详细地讲述了 Go 语言中的错误处理,并从两个视角为你总结了错误类型、错误值的处理技巧和设计方式。
在本篇,我要给你展示 Go 语言的另外一种错误处理方式。不过,严格来说,它处理的不是错误,而是异常,并且是一种在我们意料之外的程序异常。

前导知识:运行时恐慌 panic

这种程序异常被叫做 panic,我把它翻译为运行时恐慌。其中的“恐慌”二字是由 panic 直译过来的,而之所以前面又加上了“运行时”三个字,是因为这种异常只会在程序运行的时候被抛出来。
我们举个具体的例子来看看。
比如说,一个 Go 程序里有一个切片,它的长度是 5,也就是说该切片中的元素值的索引分别为01234,但是,我在程序里却想通过索引5访问其中的元素值,显而易见,这样的访问是不正确的。
Go 程序,确切地说是程序内嵌的 Go 语言运行时系统,会在执行到这行代码的时候抛出一个“index out of range”的 panic,用以提示你索引越界了。
当然了,这不仅仅是个提示。当 panic 被抛出之后,如果我们没有在程序里添加任何保护措施的话,程序(或者说代表它的那个进程)就会在打印出 panic 的详细情况(以下简称 panic 详情)之后,终止运行。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《Go语言核心36讲》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(8)

  • 江山如画
    一个函数如果要把 panic 转化为error类型值,并将其结果返回给调用方,可以考虑把 defer 语句封装到一个匿名函数之中,下面是实验的一个例子,所用函数是一个除法函数,当除数为0的时候会抛出 panic并捕获。

    func divide(a, b int) (res int, err error) {
    func() {
    defer func() {
    if rec := recover(); rec != nil {
    err = fmt.Errorf("%s", rec)
    }
    }()
    res = a / b
    }()
    return
    }

    func main() {
    res, err := divide(1, 0)
    fmt.Println(res, err) // 0 runtime error: integer divide by zero

    res, err = divide(2, 1)
    fmt.Println(res, err) // 2 <nil>
    }
    2018-10-08
    8
  • Bang
    先使用go中的类似try catch这样的语句,将异常捕获的异常转为相应的错误error就可以了
    2018-09-28
    8
  • 唐丹
    郝大,你好,我在golang 8中通过recover处理panic时发现,必须在引发panic的当前协程就处理掉,否则待其传递到父协程直至main方法中,都不能通过recover成功处理掉了,程序会因此结束。请问这样设计的原因是什么?那么协程是通过panic中记录的协程id来区分是不是在当前协程引发的panic的吗?另外,这样的话,我们应用程序中每一个通过go新起的协程都应该在开始的地方recover,否则即使父协程有recover也不能阻止程序因为一个意外的panic而挂掉?盼望解答,谢谢🙏

    作者回复: 只要在调用栈路径上就都可以处理,如果你用了defer语句和recover函数等正确处理方式还是不行的话,就要看看这个panic是不是不了恢复的。一些runtime抛出来的panic是不可恢复的,因为问题很严重必须整改代码才行。

    2018-09-28
    4
  • A 凡
    之前自己学习时候的一些模糊点更加清晰了,支持!
    2018-10-24
    1
  • 冰激凌的眼泪
    panic时,会捕获异常及异常上下文(函数名+文件行)
    类似看作有一个异常上下文列表,始于异常触发处,沿着函数调用逆向展开,每一级append自己的异常上下文,直至goroutine入口函数,最终被runtime捕获
    最终异常信息被打印,异常上下文列表被顺序打印,程序退出
    2018-10-02
    1
  • 🤔
    https://gist.github.com/bwangelme/9ce1c606ba9f69c72f82722adf1402e1
    2019-03-03
  • 虢国技匠
    打卡
    2019-01-21
  • melody_future
    panic、recover 有点像try、、catch。这样应该会好理解很多
    2018-12-25
收起评论
8
返回
顶部