@@ -26,19 +26,6 @@ func gopanic(e interface{}) {
2626 break
2727 }
2828
29- // If defer was started by earlier panic or Goexit (and, since we're back here, that triggered a new panic),
30- // take defer off list. The earlier panic or Goexit will not continue running.
31- if d.started {
32- if d._panic != nil {
33- d._panic .aborted = true
34- }
35- d._panic = nil
36- d.fn = nil
37- gp._defer = d.link
38- freedefer (d)
39- continue
40- }
41-
4229 // 标记 defer 为已启动,暂时保持在链表上
4330 // 这样 traceback 在栈增长或者 GC 的时候,能够找到并更新 defer 的参数栈帧
4431 // 并用 reflectcall 执行 d.fn
@@ -64,6 +51,7 @@ func gopanic(e interface{}) {
6451 pc := d.pc
6552 sp := unsafe.Pointer (d.sp ) // must be pointer so it gets adjusted during stack copy
6653 freedefer (d)
54+ // p.recovered 字段在 gorecover 函数中已经修改为 true 了
6755 if p.recovered {
6856 atomic.Xadd (&runningPanicDefers, -1 )
6957
@@ -83,25 +71,27 @@ func gopanic(e interface{}) {
8371 throw (" recovery failed" ) // mcall 永远不会返回
8472 }
8573 }
74+ }
8675
87- // ran out of deferred calls - old-school panic now
88- // Because it is unsafe to call arbitrary user code after freezing
89- // the world, we call preprintpanics to invoke all necessary Error
90- // and String methods to prepare the panic strings before startpanic.
91- preprintpanics (gp._panic )
92- startpanic ()
76+ ```
9377
94- // startpanic set panicking, which will block main from exiting,
95- // so now OK to decrement runningPanicDefers.
96- atomic.Xadd (&runningPanicDefers, -1 )
78+ gopanic 会把当前函数的 defer 一直执行完,其中碰到 recover 的话就会调用 gorecover 函数:
9779
98- printpanics (gp._panic )
99- dopanic (0 ) // 永远不会返回
80+ ``` go
81+ func gorecover (argp uintptr ) interface {} {
82+ gp := getg ()
83+ p := gp._panic
84+ if p != nil && !p.recovered && argp == uintptr (p.argp ) {
85+ p.recovered = true
86+ return p.arg
87+ }
88+ return nil
10089}
101-
10290```
10391
104- 可见这里面的 panic 也是一个链表,用 link 指针相连接:
92+ 很简单,就是改改 recovered 字段。
93+
94+ gopanic 里生成的 panic 对象是带指针的结构体,串成一个链表,用 link 指针相连接,并挂在 g 结构体上:
10595
10696``` go
10797// panics
0 commit comments