3.panic和recover
数据结构
type _panic struct {
argp unsafe.Pointer // 指向 defer 调用时参数的指针
arg interface{} // 调用 panic 时传入的参数
link *_panic // 链表
recovered bool // 表示当前 runtime._panic 是否被 recover 恢复
aborted bool // 表示当前的 panic 是否被强行终止
pc uintptr
sp unsafe.Pointer
goexit bool
}panic 实现
func gopanic(e interface{}) {
gp := getg()
...
var p _panic // 创建新的 panic
p.arg = e
p.link = gp._panic // 将 G 原本的 panic链表 挂到新建的 panic 后面
gp._panic = (*_panic)(noescape(unsafe.Pointer(&p))) // 将新建的 panic 链表挂到 G 上
for { // 遍历处理 G 的 defer 链表
d := gp._defer
if d == nil {
break
}
d._panic = (*_panic)(noescape(unsafe.Pointer(&p)))
reflectcall(nil, unsafe.Pointer(d.fn), deferArgs(d), uint32(d.siz), uint32(d.siz)) // 执行 defer 里的函数 d.fn
d._panic = nil
d.fn = nil
gp._defer = d.link
freedefer(d)
if p.recovered {
...
}
}
fatalpanic(gp._panic)
*(*int)(nil) = 0
}recover 实现
小结
原文链接
Last updated