济南手机网站建设公司,零售网站制作,做网站需要的参考文献,推荐 网页游戏derfer : 延迟调用#xff0c;函数结束返回时执行#xff0c;多个defer按照先进后出的顺序调用
原理#xff1a;底层通过链表实现#xff0c;每次新增的defer调用#xff0c;通过头插法插入链表#xff1b;defer执行时#xff0c;从链表头开始遍历#xff0c;相当于实…derfer : 延迟调用函数结束返回时执行多个defer按照先进后出的顺序调用
原理底层通过链表实现每次新增的defer调用通过头插法插入链表defer执行时从链表头开始遍历相当于实现了后加入的defer先执行先加的defer后执行
defer结构体
type _defer struct {started boolheap bool// openDefer indicates that this _defer is for a frame with open-coded// defers. We have only one defer record for the entire frame (which may// currently have 0, 1, or more defers active).openDefer boolsp uintptr // sp at time of deferpc uintptr // pc at time of deferfn func() // can be nil for open-coded defers_panic *_panic // panic that is running deferlink *_defer // next defer on G; can point to either heap or stack!// If openDefer is true, the fields below record values about the stack// frame and associated function that has the open-coded defer(s). sp// above will be the sp for the frame, and pc will be address of the// deferreturn call in the function.fd unsafe.Pointer // funcdata for the function associated with the framevarp uintptr // value of varp for the stack frame// framepc is the current pc associated with the stack frame. Together,// with sp above (which is the sp associated with the stack frame),// framepc/sp can be used as pc/sp pair to continue a stack trace via// gentraceback().framepc uintptr
}defer初始化
// Create a new deferred function fn, which has no arguments and results.
// The compiler turns a defer statement into a call to this.
func deferproc(fn func()) {gp : getg()if gp.m.curg ! gp {// go code on the system stack cant deferthrow(defer on system stack)}d : newdefer()if d._panic ! nil {throw(deferproc: d.panic ! nil after newdefer)}// 这里使用头插法 插入链表d.link gp._defergp._defer dd.fn fnd.pc getcallerpc()// We must not be preempted between calling getcallersp and// storing it to d.sp because getcallersps result is a// uintptr stack pointer.d.sp getcallersp()// deferproc returns 0 normally.// a deferred func that stops a panic// makes the deferproc return 1.// the code the compiler generates always// checks the return value and jumps to the// end of the function if deferproc returns ! 0.return0()// No code can go here - the C return register has// been set and must not be clobbered.
}defer执行
func deferreturn() {gp : getg()for {d : gp._deferif d nil {return}sp : getcallersp()if d.sp ! sp {return}if d.openDefer {done : runOpenDeferFrame(gp, d)if !done {throw(unfinished open-coded defers in deferreturn)}gp._defer d.linkfreedefer(d)// If this frame uses open defers, then this// must be the only defer record for the// frame, so we can just return.return}fn : d.fnd.fn nil// 指向下一个defer节点gp._defer d.linkfreedefer(d)fn()}
}