美文网首页golang
golang panic原理

golang panic原理

作者: hypercode | 来源:发表于2021-11-30 15:56 被阅读0次

    要了解panic,建议先去看一下defer的原理,具体不展开,这里只说panic。

    //runtime/runtime2.go
    type _panic struct {
        argp unsafe.Pointer // pointer to arguments of deferred call run during panic; cannot move - known to liblink
        arg interface{} // argument to panic
        link *_panic // link to earlier panic
        recovered bool // whether this panic is over
        aborted bool // the panic was aborted
    }
    

    _panic是个结构体,存储了defer指针、参数,panic列表的表头指针,和已恢复或已终止的信息,后续版本还会继续扩展这个结构体,优化panic和recover的性能。以下处理流程,在runtime.gopanic方法中,有兴趣可以直接读代码。这里只是简单描述一下,不涉及过于细节的部分。

    0、每个goroutine都有一个panic链表,运行时,遇到panic代码,会生成对应的_panic数据,存到这个链表的表头。
    1、每执行完毕一个函数,如果没有panic发生,就跳过对应的_panic数据,回到正常流程,否则进入2。
    2、如果有panic发生,处理链表中对应的_panic,进入3。
    3、如果defer链表(跟panic链表一样,也是每个goroutine一个)里存在defer,按约定顺序执行延迟代码,进入4,否则进入7。
    4、当defer链表执行到需要recover的时候,就交给reflectcall去调用gorecover,进入5,否则进入6。
    5、执行recover,这时对应的_panic结构里的recovered字段标记为真,由recovery方法,负责安抚当前的_panic,回到正常流程(这个地方的处理,依赖deferproc方法,自己去读代码)。
    6、如果没recover,那就进入死给你看流程,进入7。
    7、比较厚道的执行preprintpanics方法,打印出所涉及的 panic 消息,进入8。
    8、最后,执行fatalpanic方法,宣布老子不玩了。

    套娃问题:当执行defer链表中的defer的时候,可能会有新的panic产生,此时会把当前的_panic标记为放弃,进入新产生的_panic处理流程。

    特别提示:因为Golang的gorotuine机制,panic在不同的gorotuine里面,是单独的,并不是整体处理。可能一个地方凉了,就会整体完蛋,这个要非常小心。

    相关文章

      网友评论

        本文标题:golang panic原理

        本文链接:https://www.haomeiwen.com/subject/piydxrtx.html