当前位置: 首页 > news >正文

golang defer实现

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 can't 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 getcallersp's 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()}
}
http://www.lryc.cn/news/334978.html

相关文章:

  • 数据仓库实践
  • 深入浅出 -- 系统架构之微服务标准组件及职责
  • IP协议中的四大支柱:DHCP、NAT、ICMP和IGMP的功能剖析
  • 基于Socket简单的UDP网络程序
  • 计算机思维
  • 如何判断一个linux机器是物理机还是虚拟机
  • python用requests的post提交data数据以及json和字典的转换
  • 【Datax分库分表导数解决方法】MySQL_to_Hive
  • Vue2 —— 学习(一)
  • Windows Server 2008添加Web服务器(IIS)、WebDAV服务、网络负载均衡
  • SpringMVC转发和重定向
  • 勒索病毒最新变种.rmallox勒索病毒来袭,如何恢复受感染的数据?
  • 复试专业课问题
  • 比特币革命:刚刚开始
  • 淘宝店商家电话提取软件操作经验
  • 【进阶六】Python实现SDVRPTW常见求解算法——遗传算法(GA)
  • 【Android】App通信基础架构相关类源码解析
  • 06-kafka配置
  • Git、TortoiseGit、SVN、TortoiseSVN 的关系和区别
  • 4月5日排序算法总结(1)
  • Pandas追加写入文件的时候写入到了第一行
  • 04---webpack编写可维护的构建配置
  • 【云计算】云数据中心网络(一):VPC
  • 自动驾驶中的多目标跟踪_第一篇
  • AI爆款文案 巧用AI大模型让文案变现插上翅膀
  • Python入门的60个基础练习(一)
  • 微软云学习环境
  • 大厂面试:找出数组中第k大的数的最佳算法
  • 爬取高校专业信息的Python爬虫简介与实践
  • redis 集群模式(redis cluster)介绍