延宕执行,妙用无穷,Go lang1.18入门精炼教程,由白丁入鸿儒,Golang中defer关键字延迟调用机制使用EP17

先行定义,延后执行。不得不佩服Go lang设计者天才的设计,事实上,defer关键字就相当于Python中的try{ ...}except{ ...}finally{...}结构设计中的finally语法块,函数结束时强制执行的代码逻辑,但是defer在语法结构上更加优雅,在函数退出前统一执行,可以随时增加defer语句,多用于系统资源的释放以及相关善后工作。当然了,这种流程结构是必须的,形式上可以不同,但底层原理是类似的,Golang 选择了更简约的defer,避免多级嵌套的try except finally 结构。

使用场景

操作系统资源在业务上避免不了的,比方说单例对象的使用权、文件读写、数据库读写、锁的获取和释放等等,这些资源需要在使用完之后释放掉或者销毁,如果忘记释放、资源会常驻内存,长此以往就会造成内存泄漏的问题。但是人非圣贤,孰能无过?因此研发者在撰写业务的时候有几率忘记关闭这些资源。

Golang中defer关键字的优势在于,在打开资源语句的下一行,就可以直接用defer语句来注册函数结束后执行关闭资源的操作。说白了就是给程序逻辑“上闹钟”,定义好逻辑结束时需要关闭什么资源,如此,就降低了忘记关闭资源的概率:

这里通过gorm获取数据库指针变量后,在业务开始之前就使用defer定义好数据库链接的关闭,在main函数执行完毕之前,执行db.Close()方法,所以打印语句是在defer之前执行的。

所以需要注意的是,defer最好在业务前面定义,如果在业务后面定义:

这样写就是画蛇添足了,因为本来就是结束前执行,这里再加个defer关键字的意义就不大了,反而会在编译的时候增加程序的判断逻辑,得不偿失。

defer执行顺序问题

Golang并不会限制defer关键字的数量,一个函数中允许多个“延迟任务”:

程序返回:

我们可以看到,多个defer的执行顺序其实是“反”着的,先定义的后执行,后定义的先执行,为什么?因为defer的执行逻辑其实是一种“压栈”行为:

这里我们使用切片和结构体实现了栈的数据结构,当元素入栈的时候,会进入栈底,后进的会把先进的压住,出栈则是后进的先出:

程序返回:

所以,在defer执行顺序中,业务上需要先执行的一定要后定义,而业务上后执行的一定要先定义。

除此以外,就是与其他执行关键字的执行顺序问题,比方说return关键字:

程序返回:

一般情况下,我们会认为return就是结束逻辑,所以return逻辑应该会最后执行,不是原子操作,在底层分为两步来执行,第一步赋值返回值,第二步进行返回,函数中如果存在defer,那么defer执行的时机是在第一步和第二步之间,也就是defer会在retrun第一步赋值的后面执行。

业务与特性结合

我们知道,有些内置关键字不仅仅具备表层含义,如果了解其特性,是可以参与业务逻辑的,比如说Python中的try{ ...}except{ ...}finally{...}结构,表面上是捕获异常,输出异常,其实可以利用其特性搭配唯一索引,就可以直接完成排重业务,从而减少一次磁盘的IO操作。

defer也如此,假设我们要在同一个函数中打开不同的文件进行操作:

所以理论上,需要两个文件句柄对象,分别打开不同的文件,然后同步执行。

但让defer关键字参与进来:

这里就用到了defer的特性,defer函数定义的时候,句柄参数就已经复制进去了,随后,真正执行close()函数的时候就刚好关闭的是对应的文件了,如此,同一个句柄对不同文件进行了复用,我们就节省了一次内存空间的分配。

defer一定会执行吗

我们知道Python中的try{ ...}except{ ...}finally{...}结构,finally仅仅是理论上会执行,一旦遇到特殊情况:

程序返回:

并未执行print("db is opening")逻辑,是因为在__enter__方法中就已经结束了(exit(-1))

而defer同理:

这里和Python一样,同样调用os包中的Exit函数,程序返回:

延迟方法并未执行,所以defer并非一定会执行。

结语

defer关键字是极其天才的设计,业务简单的情况下不会有什么问题。但也需要深入理解defer的特性以及和其他内置关键字的关系,才能发挥它最大的威力,著名语言C#最新版本支持了 using无括号的形式,默认当前块结束时释放资源,这也算是对defer关键字的一种致敬罢。

最新资讯

文档百科

黑卷尾鸟怎样分辨雌雄 黑卷尾鸟公母怎么分

黑卷尾雄性成鸟(繁殖羽):全身羽毛呈辉黑色;前额、眼先羽绒黑色。上体自头部、背部至腰部及尾上覆羽,概深黑色,缀铜绿色金属闪光。尾羽深黑色,羽表面沾铜绿色光泽;中央一对尾羽最短,向外侧依次顺序增长,最外侧一对最长,其末端向外上方卷曲,尾羽末端呈深叉状;翅黑褐色,飞羽外翈及翅上覆羽具铜绿色金属光泽。

酒精中毒怎么办 食物解酒精中毒方法

酒精以不同的比例存在于各种酒中,它在人体内可以很快发生作用,改变人的情绪和行为。这是因为酒精在人体内不需要经过消化作用,接下来酒妖网的小编就带大家了解酒精中毒怎么办和食物解酒精中毒方法吧。血中酒精浓度达到0.1%左右。酒后多饮白糖水,可以达到解酒之功效。如果发现中毒迹象,想办法让他吐出来,这样防止中毒程度变大。

西码丽运动内衣怎么样 西码丽运动内衣舒服吗

西码丽运动内衣是网上很有名的一个牌子,这个品牌的很多贴身运动服装都还是不错的,很受女孩子的喜欢,下面一起来了解下西码丽运动内衣怎么样吧。西码丽运动内衣怎么样西码丽运动内衣号码印在背心上,还挺有特色的。西码丽运动内衣质地顺滑且弹性大,不会有勒紧的感觉。

多方反攻大盘2930点会回来吗

午后,两市震荡调整,多个板块出现回落,市场在震荡中再次走弱。尾盘指数企稳回升,最终上证指数重回2900点。截至收盘,上证指数上涨0.80%,收于2923.28点,成交量有所放大,全天成交额为1789亿元;深证成指上涨0.99%,收于9266.30点;创业板指上涨1.22%,收于1553.72点;上证50指数上涨0.88%,站上30日线,收于2906.55点,全天成交额为404.4亿元。

ph9.0苏打水有什么作用

苏打水是碳酸氢钠的水溶液,含有弱碱性,对传输氧气,调节新陈代谢,排除酸性废物和预防疾病是非常必要的。如果胃酸分泌较少的话长期饮用苏打水也会造成伤害。苏打水有抗氧化作用,能预防皮肤老化。适当饮用苏打水有助于调节消化功能,缓解消化不良症状。苏打水能够加快酒精在人体的代谢速率,减少酒精对肝脏的伤害,是配酒的最佳伴侣!

烹饪时水要怎么用

化冻用冷水,冻肉、冻虾等用热水化冻会失去鲜味。直接用冷水做清炖鱼或鱼汤无腥味,但必须一次放足,如果中途加水,会减少原来的鲜味。煮肉或煮骨头汤时应用凉水,并逐渐加温,煮沸后用文火慢炖。蒸鸡蛋羹时要用温开水搅,蛋羹鲜嫩。煎荷包蛋时,在蛋黄即将凝固之际,可浇上一汤匙冷开水,会使蛋熟后又黄又嫩,色味俱佳。

CopyRight © 2000~2023 一和一学习网 Inc.All Rights Reserved.
一和一学习网:让父母和孩子一起爱上学习