本篇文章基于 Golang 1.17.2

书接上回,胖虎前几天面试了一个“双休”的公司,但是他并不想去,他觉得他配不上这么优秀的公司,于是又开始了漫长的面试之路。

面试官:“看你简历上面写着精通 Golang, 那我问个简单的问题吧,什么defer”

胖虎:defer语句注册了一个函数调用,这个调用会延迟到defer语句所在的函数执行完毕后执行,所谓执行完毕是指该函数执行了return语句、函数体已执行完最后一条语句或函数所在的协程发生了panic。

胖虎回答问后,心想:“我厉害吧,把defer语句的官方解释都背下来了,作为优质的八股文选手,快给我发offer吧!!老板,走过路过,不要错过”

面试官看着胖虎自己在那演戏,笑而不语。继续问道:“那你说说为什么需要defer吧”

为什么需要defer

胖虎:在写代码的时候,经常会需要申请一些资源,比如数据库连接、mysql事务的提交等。

但是经常忘记释资源,并且释放的地方太多

导致很多重复代码,很容易出现事故。

defer关键字就可以解决此类问题,

在函数运行完毕后,释放响应的资源。

面试官:“那你说下defer常见的应用场景吧”

defer的执行顺序

多个defer出现的时候,它是一个“栈”的关系,也就是先进后出。一个函数中,写在前面的defer会比写在后面的defer调用得晚。

执行结果如下:

原因如下

defer与return

执行结果如下:

结论为:return之后的语句先执行,defer后的语句后执行

defer与panic

执行结果如下:

结论为:遇到panic时,遍历本协程的defer链表,并执行defer。在执行defer过程中:遇到recover则停止panic,返回recover处继续往下执行。

defer与os.Exit()

执行结果如下:

结论:当发生panic时,defer会被执行,但是当调用os.Exit()方法退出程序时,defer并不会被执行。

defer遇到返回值为命名变量

最终结果是:

原因:

  1. 11行res变量为"", 12行res值为"res"
  2. 执行return语句将"我是最终结果"赋值给变量res
  3. 执行defer方法,将res 修改为"我是defer"
  4. 最终结果就是“我是defer”

defer遇到返回值为匿名变量

执行结果是:

执行步骤:

  1. 11行res变量为"", 12行res值为"res"
  2. 执行return语句将"我是最终结果"赋值给匿名变量
  3. 执行defer方法,将res 修改为"我是defer", 但对匿名变量并没有影响
  4. 最终结果就是“我是最终结果”

总结如下:

胖虎一口气说了这么多,内心想:这次志在必得啊。我明天就能入职,快找我进来吧

面试官:小伙子不错啊,这样吧,在面试你最后一题,你要是能答上来,薪资大胆要,要多少,我们就给多少。

以下代码执行结果是什么?为什么?

胖虎:“……”,这题不会啊,眼看煮熟的鸭子飞跑了,胖虎流下没有技术的泪水。

面试官:不着急,看你的确挺厉害的,给你一次场外求助的机会,读者在评论区留言,在评论区选择出认为对的答案,也算面试成功。

胖虎:“有知道的大佬吗?在线等”

福利

我为大家整理了一些学习资料礼包,关注公众号回复指令:【Golang】、【操作系统】、【Linux】、【LeetCode】、【Golang电子书】即可获得相应学习资料!