panic/

directory
v0.0.0-...-ce13bd1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 6, 2023 License: MIT

README

panic

panic 只会触发当前 Goroutine 的 defer; recover 只有在 defer 中调用才会生效; panic 允许在 defer 中嵌套多次调用;

数据结构 runtime._panic

type _panic struct {
	argp      unsafe.Pointer
	arg       interface{}
	link      *_panic
	recovered bool
	aborted   bool
	pc        uintptr
	sp        unsafe.Pointer
	goexit    bool
}

argp 是指向 defer 调用时参数的指针; arg 是调用 panic 时传入的参数; link 指向了更早调用的 runtime._panic 结构; recovered 表示当前 runtime._panic 是否被 recover 恢复; aborted 表示当前的 panic 是否被强行终止;

panic 函数可以被连续多次调用,它们之间通过 link 可以组成链表。

编译器会将关键字 panic 转换成 runtime.gopanic,该函数的执行过程包含以下几个步骤:

创建新的 runtime._panic 并添加到所在 Goroutine 的 _panic 链表的最前面; 在循环中不断从当前 Goroutine 的 _defer 中链表获取 runtime._defer 并调用 runtime.reflectcall 运行延迟调用函数; 调用 runtime.fatalpanic 中止整个程序;

编译器会将关键字 recover 转换成 runtime.gorecover:

编译器会负责做转换关键字的工作; 将 panic 和 recover 分别转换成 runtime.gopanic 和 runtime.gorecover; 将 defer 转换成 runtime.deferproc 函数; 在调用 defer 的函数末尾调用 runtime.deferreturn 函数; 在运行过程中遇到 runtime.gopanic 方法时,会从 Goroutine 的链表依次取出 runtime._defer 结构体并执行; 如果调用延迟执行函数时遇到了 runtime.gorecover 就会将 _panic.recovered 标记成 true 并返回 panic 的参数; 在这次调用结束之后,runtime.gopanic 会从 runtime._defer 结构体中取出程序计数器 pc 和栈指针 sp 并调用 runtime.recovery 函数进行恢复程序; runtime.recovery 会根据传入的 pc 和 sp 跳转回 runtime.deferproc; 编译器自动生成的代码会发现 runtime.deferproc 的返回值不为 0,这时会跳回 runtime.deferreturn 并恢复到正常的执行流程; 如果没有遇到 runtime.gorecover 就会依次遍历所有的 runtime._defer,并在最后调用 runtime.fatalpanic 中止程序、打印 panic 的参数并返回错误码 2;

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL