Golang defer 使用及面试常见的坑

前言

defer是Golang中一个常用的关键字,通常用来做一些收尾工作。比如开启了一个东西,就顺手defer中关闭。对于面试,defer也算一个高频考点,尤其是他的许多个坑,因此本文主要复习一下defer的用法

在这里插入图片描述

多个defer的执行顺序

通常来说,defer是在程序的最后才执行。当多个defer出现时,遵循 栈 的先入后出顺序执行。

前言

defer是Golang中一个常用的关键字,通常用来做一些收尾工作。比如开启了一个东西,就顺手defer中关闭。对于面试,defer也算一个高频考点,尤其是他的许多个坑,因此本文主要复习一下defer的用法

多个defer的执行顺序

通常来说,defer是在程序的最后才执行。当多个defer出现时,遵循 栈 的先入后出顺序执行。

在这里插入图片描述

deferreturn一起使用

关于deferreturn的执行顺序,普遍来说是先returndefer,可以参考此例。(直接cv一个,懒得写了)。

package mainimport "fmt"func deferFunc() int {fmt.Println("defer func called")return 0
}func returnFunc() int {fmt.Println("return func called")return 0
}func returnAndDefer() int {defer deferFunc()return returnFunc()
}func main() {returnAndDefer()
}————————————————
原文作者:刘丹冰Aceld
转自链接:https://learnku.com/articles/42255
版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请保留以上作者信息和原文链接。

执行结果
return func called
defer func called

此篇文章中是分了多点来概述此情况——
“知识点 2: defer 与 return 谁先谁后”,
“知识点 3:函数的返回值初始化”,
“知识点 4: 有名函数返回值遇见 defer 情况”

但我认为这样理解下来较为复杂,因此参考了此文,从return的角度来理解,将其归纳在一起。

return并不是原子操作,而是分为:赋值、返回 两个步骤。
加上defer,三者的执行时机则是:赋值、defer、return。

不带命名返回值

因此对应来看,对于“不带命名返回值”的情况,即func test() int这样的情况,由于return的值相当于是编译器自己新建的一个var tmp int,而defer中进行赋值操作则不会影响tmp,因此不影响返回值。

package mainimport "fmt"func main() {t := test()fmt.Println(t)
}func test() int { //无名返回i:=9defer func() {i++fmt.Println("defer1=", i)}()defer func() {i++fmt.Println("defer2=", i)}()return i
} 作者:蓝色记忆
链接:https://juejin.cn/post/7095631673865273352
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

此例中,输出内容是:

defer2= 10
defer1= 11
9 

可以理解为,系统var tmp int,这个tmp是需要返回的值,他是9。但是defer修改的是i,所以互不干涉。

有名返回值

对于有名返回值的情况,由于有名,所以没有了var tmp int这一步,defer中执行的修改会影响return的值,因此会影响。

defer配合panicrecover

参考此文

参考资源

https://learnku.com/articles/42255

https://juejin.cn/post/7095631673865273352

https://juejin.cn/post/7304183399885996067

deferreturn一起使用

关于deferreturn的执行顺序,普遍来说是先returndefer,可以参考此例。(直接cv一个,懒得写了)。

package mainimport "fmt"func deferFunc() int {fmt.Println("defer func called")return 0
}func returnFunc() int {fmt.Println("return func called")return 0
}func returnAndDefer() int {defer deferFunc()return returnFunc()
}func main() {returnAndDefer()
}————————————————
原文作者:刘丹冰Aceld
转自链接:https://learnku.com/articles/42255
版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请保留以上作者信息和原文链接。

执行结果
return func called
defer func called

此篇文章中是分了多点来概述此情况——
“知识点 2: defer 与 return 谁先谁后”,
“知识点 3:函数的返回值初始化”,
“知识点 4: 有名函数返回值遇见 defer 情况”

但我认为这样理解下来较为复杂,因此参考了此文,从return的角度来理解,将其归纳在一起。

return并不是原子操作,而是分为:赋值、返回 两个步骤。
加上defer,三者的执行时机则是:赋值、defer、return。

不带命名返回值

因此对应来看,对于“不带命名返回值”的情况,即func test() int这样的情况,由于return的值相当于是编译器自己新建的一个var tmp int,而defer中进行赋值操作则不会影响tmp,因此不影响返回值。

package mainimport "fmt"func main() {t := test()fmt.Println(t)
}func test() int { //无名返回i:=9defer func() {i++fmt.Println("defer1=", i)}()defer func() {i++fmt.Println("defer2=", i)}()return i
} 作者:蓝色记忆
链接:https://juejin.cn/post/7095631673865273352
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

此例中,输出内容是:

defer2= 10
defer1= 11
9 

可以理解为,系统var tmp int,这个tmp是需要返回的值,他是9。但是defer修改的是i,所以互不干涉。

有名返回值

对于有名返回值的情况,由于有名,所以没有了var tmp int这一步,defer中执行的修改会影响return的值,因此会影响。

defer配合panicrecover

参考此文

参考资源

https://learnku.com/articles/42255

https://juejin.cn/post/7095631673865273352

https://juejin.cn/post/7304183399885996067

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/341767.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

查询分组功能:发布不同班级查询,支持独立分组链接和二维码

期末考试已经陆续开始,老师如果负责多个班级或年级,如何在一个账号中实现不同班级单独一个查询页呢? 易查分的【查询分组功能】就可实现,本次就来介绍如何使用此功能。 📖案例:负责相关工作的老师&#xff…

如何选择最适合的采购付款 (P2P) 解决方案?

无论企业的业务流程执行得如何,流程中始终存在改进空间。更好的管理系统是获得更好结果的关键,尤其是当企业处于增长阶段时。强大的采购到付款(P2P)系统是加快采购流程,同时保持采购支出可见性的最有效方法之一。 什么…

YOLOv5改进 | 检测头篇 | ASFFHead自适应空间特征融合检测头(全网首发)

一、本文介绍 本文给大家带来的改进机制是利用ASFF改进YOLOv5的检测头形成新的检测头Detect_ASFF,其主要创新是引入了一种自适应的空间特征融合方式,有效地过滤掉冲突信息,从而增强了尺度不变性。经过我的实验验证,修改后的检测头在所有的检测目标上均有大幅度的涨点效果,…

Open CV 图像处理基础:(五)Java 使用 Open CV 的绘图函数

Java 使用 Open CV 的绘图函数 使用 Open CV 在 Java 中对图片使用绘图函数,分别绘制矩形、斜线、圆形、椭圆形以及添加文本 Java 使用 Open CV 的绘图函数 Java 使用 Open CV 的绘图函数函数绘制矩形绘制线绘制圆形绘制椭圆添加文本 代码示例Open CV 专栏导航 函…

12GoF之代理模式

解决问题的思维:AOP 解决问题技术:代理技术 代理技术太麻烦,因此使用框架 Spring AOP框架(底层是代理技术:jdk动态daili,cglib) 代理模式是GoF23种设计模式之一。属于结构型设计模式。 代理…

网络层详解

目录 前言 一、IP协议 1、IP协议报头 2、协议字段理解 (1)4位版本 (2)4位首部长度 (3)8位服务类型 (4)16位总长度 (5)标识、标志与片偏移 &#xf…

C2855 命令行选项“/Zc:referenceBinding“与预编译头不一致和C2855 命令行选项“/Zc:__cplusplus“与预编译头不一致

在VS2019和Qt5.12.12环境下,笔记本上编译这个工程没有问题,把工程拷贝到台式机上,一样的配置,但是报如下错误: 打开项目的命令行配置如下: 解决办法:在编译选项"/Zc:referenceBinding"…

Ubuntu server搭建dhcp服务器

安装 直接使用一下命令进行安装 apt-get install isc-dhcp-server 以下就是安装好的图片 然后进入dhcp目录 cd /etc/dhcp 进入后用ls查看当前目录存在哪些文件 使用如下进入dhcp.conf vim dhcpd.conf 红:设置ip域和子网掩码 绿:设置ip池范围 黄…

永磁同步电机的磁场定向控制

目录 概述 通过系统仿真验证行为 探索模型架构 生成用于集成到嵌入式应用程序的控制器 C 代码 指定控制器模型的参考行为 创建 PIL 实现 准备用于 PIL 测试的控制器模型 测试生成的代码的行为和执行时间 结论 此示例说明从电机控制算法生成 C 代码并验证其编译行为和执…

【java八股文】之Java基础篇

1、Java有哪几种数据类型 基本数据类型:byte(1字节) short(2字节) int(4字节) long(8字节) float(4字节) double(8字节) char(2字节&a…

BP神经网络(公式推导+举例应用)

文章目录 引言M-P神经元模型激活函数多层前馈神经网络误差逆传播算法缓解过拟合化结论实验分析 引言 人工神经网络(Artificial Neural Networks,ANNs)作为一种模拟生物神经系统的计算模型,在模式识别、数据挖掘、图像处理等领域取…

基于Flask的高并发部署方案

文章目录 Flask方案简介服务端代码客户端代码 Gevent Flask方案简介安装示例 gunicornFlask 部署服务简介安装示例 在AI部署方案中,Flask是最常用的方案!本文列举几种最常用基于Flask的部署方案。 Flask方案 简介 Flask 是一个轻量级的 Python Web 框架…