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 ...
随机推荐
- 射线与空间内三角形的相交检测算法(Möller-Trumbore)的推导与实践
背景介绍(学习算法之前需要先了解) 射线与空间内三角形的相交检测是游戏程序设计中一个常见的问题,最典型的应用就是拾取(Picking),本文介绍一个最常见的方法,这个方法也是DirectX中采用的方法 ...
- Java on Visual Studio Code的更新 – 2021年4月
杨尧今 from Microsoft VS Code Java Team 欢迎来到这一期的VS Code Java更新.又是一个忙碌而富有成效的月份. Java调试器和Java测试扩展获得了新功能.在 ...
- primary key
只要使用innodb就要为表指定主键: 如果不指定mysql就会自己找不为空且为一的作为主键,如果找不到,就会使用默认的(软件自己预定好的)作为主键: 主键分为单列主键和复合主键,用法和单列唯一,联合 ...
- ThreadLocal内存溢出代码演示和原因分析!
ThreadLocal 翻译成中文是线程本地变量的意思,也就是说它是线程中的私有变量,每个线程只能操作自己的私有变量,所以不会造成线程不安全的问题. 线程不安全是指,多个线程在同一时刻对同一个全局 ...
- k8s运行容器之Job应用(6)
容器按照持续运行的时间可分为两类:服务类容器和工作类容器. 服务类容器通常持续提供服务,需要一直运行,比如 http server,daemon 等.工作类容器则是一次性任务,比如批处理程序,完成后容 ...
- 云计算OpenStack---虚拟机获取不到ip(12)
一.现象描述 openstack平台中创建虚拟机后,虚拟机在web页面中显示获取到了ip,但是打开虚拟机控制台后查看网络状态,虚拟机没有ip地址,下图为故障截图: 二.分析 1.查看neutron服务 ...
- 也谈如何写一个Webserver(三)
在上一篇里,我介绍了如何应用socket和epoll来组织和管理从客户端(如,浏览器)传入的连接,通过设置非阻塞连接让Webserver有更好的性能. 下面,我介绍一下在我写的Webserver Ma ...
- 学完了这篇JVM,面试官真拿我没办法了!
在我们面试中经常会遇到面试官问一些有关JVM的问题,下面我大概从运行时数据域.类加载机制.类加载器.垃圾收集器.垃圾收集算法.JVM堆内存模型.JVM内存结构.JVM调优等几个方面来讲一下JVM. 一 ...
- F5 BIG-IQ 8.0 发布 - 借助一个统一的管理平台,管理您的所有 BIG-IP 设备和服务
针对完整可见性和控制的 BIG-IQ 集中式管理 BIG-IP 设备和服务的端到端控制 高效管理(编排.可见性和合规性)依赖于跨本地和云部署中始终如一的应用服务和安全策略.利用独立统一的管理平台实现对 ...
- visudo
修改sudo配置 sudo visudo 上面的意思是执行visudo这个命令, visudo其实就是用vi编辑器来编辑/etc/sudoers, 这个文件只能通过visudo来修改 或者在/etc/ ...