golang中的defer和return的执行顺序
结论
go中是先给return准备返回值,再根据defer先进后出的规则执行,最后将返回值返回给调用者
测试用例1验证分析
代码片段如下:
func foo_1() (err error) {
defer func() {
fmt.Println(err)
err = errors.New("a")
}()
defer func(e error) {
fmt.Println(e)
e = errors.New("b")
}(err)
err = errors.New("c")
return err
}
func TestDeferAndReturn(t *testing.T) {
fmt.Println(foo_1())
}
分析:
- 第一步:函数foo_1()执行到return关键字时,先准备好返回值,err=c
- 第二步:进入第二个defer函数,这里面进行了值拷贝,将err拷贝给了e,所以这里打印的e是nil,之后将e赋值也是不影响err的值的,err还是c
- 第三步:进入第一个defer函数,这里先打印了err,还是c,然后对err进行了赋值,err值变为a
- 第四步:经过defer的操作,现在的err值变为了a,故返回给调用者是a
这个测试用例的输出如下
=== RUN TestDeferAndReturn
c
a
--- PASS: TestDeferAndReturn (0.00s)
PASS
Process finished with exit code 0
测试用例2验证分析
代码片段如下:
func foo_2() error {
var err error
defer func() {
fmt.Println(err)
err = errors.New("a")
}()
defer func(e error) {
fmt.Println(e)
e = errors.New("b")
}(err)
err = errors.New("c")
return err
}
func TestDeferAndReturn(t *testing.T) {
fmt.Println(foo_2())
}
分析:
这里的返回值是匿名返回写法,这种情况下,return会首先创建一个临时变量temp,然后将err赋值给temp,后续两个defer中对err的操作并不会影响到temp中的值,所以这里返回给调用者的是c
这个测试用例的输出如下
=== RUN TestDeferAndReturn
c
c
--- PASS: TestDeferAndReturn (0.00s)
PASS
Process finished with exit code 0
golang中的defer和return的执行顺序的更多相关文章
- go defer、return的执行顺序
一.一个函数中多个defer的执行顺序 defer 的作用就是把defer关键字之后的函数执行压入一个栈中延迟执行,多个defer的执行顺序是后进先出LIFO,也就是先执行最后一个defer,最后执行 ...
- java中异常处理finally和return的执行顺序
根据个人亲自测试,得出如下结果: 1.try,catch中有没有return,finnally都会执行,而且是先执行try,catch后,最后执行finnally语句: 2.如果finnally中有r ...
- 我敢说你不一定完全理解try 块,catch块,finally 块中return的执行顺序
大家好,今天我们来讲一个笔试和面试偶尔都会问到的问题,并且在工作中不知道原理,也会造成滥用. 大家可能都知道,try 块用来捕获异常,catch块是处理try块捕获的异常,finally 块是用来关闭 ...
- Asp.Net WebAPI中Filter过滤器的使用以及执行顺序
转发自:http://www.cnblogs.com/UliiAn/p/5402146.html 在WEB Api中,引入了面向切面编程(AOP)的思想,在某些特定的位置可以插入特定的Filter进行 ...
- python 中多个装饰器的执行顺序
python 中多个装饰器的执行顺序: def wrapper1(f1): print('in wrapper1') def inner1(*args,**kwargs): print('in inn ...
- [Vue]vue中各选项及钩子函数执行顺序
在vue中,实例选项和钩子函数和{{}}表达式都是不需要手动调用就可以直接执行的. 一.生命周期图示 二.vue中各选项及钩子函数执行顺序 1.在页面首次加载执行顺序有如下: beforeCreate ...
- java 中 this 和 super 说明及在构造器中super()和this()相互调用执行顺序
this this 表示当前对象 使用上细分的话,this有 this. 和this()的使用情况 ,下面我们开始细撸 this . 使用场景一: 在成员方法中,this.变量名 指带当前对象的变量, ...
- golang中的defer
1.defer的作用 defer 语句会将函数推迟到外层函数返回之后执行. 即defer后面的函数在defer语句所在的函数执行结束的时候会被调用 2.defer的语法 defer后面必须是函数调用语 ...
- java中finally和return的执行顺序
注意:return的位置... 从这几个例子中可以看到,如果try之前没有有条件的return,则try..catch..finally语句块中的语句都是顺序执行(如果try中或者catch中 有re ...
随机推荐
- 初窥软件工程 2020BUAA软件工程$\cdot$个人博客作业
初窥软件工程 2020BUAA软件工程\(\cdot\)个人博客作业 目录 初窥软件工程 2020BUAA软件工程$\cdot$个人博客作业 一.作业要求简介 二.正文 (一) 快速看完整部教材,列出 ...
- 【BUAA软工】提问回顾与个人总结
链接到以前提问题的博客 在之前的博客我曾经提问过以下几个问题 为什么单元测试必须由写程序的人完成? 过早优化,过早泛华:何时为过早? 为何使用goto语句? 用户需求分析:分而治之,如何分? 兼容性测 ...
- VS·卸载进程卡死"正在配置您的系统,这可能需要一些时间"
阅文时长 | 0.34分钟 字数统计 | 596.8字符 主要内容 | 1.引言&背景 2.声明与参考资料 『VS·卸载进程卡死"正在配置您的系统,这可能需要一些时间"』 ...
- 技术干货 | 基于MindSpore更好的理解Focal Loss
[本期推荐专题]物联网从业人员必读:华为云专家为你详细解读LiteOS各模块开发及其实现原理. 摘要:Focal Loss的两个性质算是核心,其实就是用一个合适的函数去度量难分类和易分类样本对总的损失 ...
- goland:调试
弹出框f9 会跳转到下一个断点
- Linux_WEB访问控制示例(使用IPADDR类型)
前言: WEB服务使用访问控制,可以控制IP.主机名.以及某个网段的IP去访问我们的WEB服务,从而加减少流量的访问 一.使用IP控制访问 1.在/var/www/html下创建一个可访问的测试页面 ...
- Redis 为什么使用跳跃表
引言 跳跃表是一种有序的数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的. 什么是跳跃表 对于一个单链表来讲,即便链表中存储的数据是有序的,如果我们要想在其中查找某个 ...
- MyBatis 全局配置文件详解(七)
MyBatis 配置文件作用 MyBatis配置文件包含影响 MyBatis 框架正常使用的功能设置和属性信息.它的作用好比手机里的设置图标,点击这个图标就可以帮助我们查看手机的属性信息和设置功能.其 ...
- 原型和原型链 prototype和proto的区别
原型 原型是function对象下的属性,它定义了构造函数的共同祖先,也就是一个父子级的关系,子对象会继承父对象的方法和属性 prototype是函数下的属性,对象想要查看原型使用隐式属性__Prot ...
- Systemverilog MCDF寄存器描述
前三个寄存器是读写寄存器(控制寄存器) (一)地址0x00 :32bit bit[0]通道使能,1打开,0关闭.复位1. bit[2:1]优先级,0最高 bit[5:3]数据包长度,是解码对应的. 0 ...