结论

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的执行顺序的更多相关文章

  1. go defer、return的执行顺序

    一.一个函数中多个defer的执行顺序 defer 的作用就是把defer关键字之后的函数执行压入一个栈中延迟执行,多个defer的执行顺序是后进先出LIFO,也就是先执行最后一个defer,最后执行 ...

  2. java中异常处理finally和return的执行顺序

    根据个人亲自测试,得出如下结果: 1.try,catch中有没有return,finnally都会执行,而且是先执行try,catch后,最后执行finnally语句: 2.如果finnally中有r ...

  3. 我敢说你不一定完全理解try 块,catch块,finally 块中return的执行顺序

    大家好,今天我们来讲一个笔试和面试偶尔都会问到的问题,并且在工作中不知道原理,也会造成滥用. 大家可能都知道,try 块用来捕获异常,catch块是处理try块捕获的异常,finally 块是用来关闭 ...

  4. Asp.Net WebAPI中Filter过滤器的使用以及执行顺序

    转发自:http://www.cnblogs.com/UliiAn/p/5402146.html 在WEB Api中,引入了面向切面编程(AOP)的思想,在某些特定的位置可以插入特定的Filter进行 ...

  5. python 中多个装饰器的执行顺序

    python 中多个装饰器的执行顺序: def wrapper1(f1): print('in wrapper1') def inner1(*args,**kwargs): print('in inn ...

  6. [Vue]vue中各选项及钩子函数执行顺序

    在vue中,实例选项和钩子函数和{{}}表达式都是不需要手动调用就可以直接执行的. 一.生命周期图示 二.vue中各选项及钩子函数执行顺序 1.在页面首次加载执行顺序有如下: beforeCreate ...

  7. java 中 this 和 super 说明及在构造器中super()和this()相互调用执行顺序

    this this 表示当前对象 使用上细分的话,this有 this. 和this()的使用情况 ,下面我们开始细撸 this . 使用场景一: 在成员方法中,this.变量名 指带当前对象的变量, ...

  8. golang中的defer

    1.defer的作用 defer 语句会将函数推迟到外层函数返回之后执行. 即defer后面的函数在defer语句所在的函数执行结束的时候会被调用 2.defer的语法 defer后面必须是函数调用语 ...

  9. java中finally和return的执行顺序

    注意:return的位置... 从这几个例子中可以看到,如果try之前没有有条件的return,则try..catch..finally语句块中的语句都是顺序执行(如果try中或者catch中 有re ...

随机推荐

  1. .NET平台系列10 .NET统一平台愿景

    系列目录     [已更新最新开发文章,点击查看详细] 2019年,微软分享了[统一的.NET堆栈和生态系统的愿景].给开发者带来的价值是,将能够使用一组API,语言和工具来针对广泛的应用程序类型,包 ...

  2. [Linux] 完全卸载mysql

    参考 https://www.jianshu.com/p/ef58fb333cd6

  3. CSS中的颜色、长度、角度、时间

    一.颜色的表示方法 颜色是通过对红.绿和蓝光的组合来显示的. 1.颜色名 1 <!DOCTYPE html> 2 <html lang="en"> 3 &l ...

  4. [Linux] Linux C编程一站式学习 Part.3

    Linux系统编程 文件与I/O C标准I/O库函数与Unbuffered I/O函数 C标准I/O库函数printf().putchar().fputs(),会在用户空间开辟I/O缓冲区 系统函数o ...

  5. Linux下Shell实现服务器IP监测

    实验室有一个服务器放在机房,装的是Ubuntu Server,IP为自动分配,因此一旦IP有变化就无法远程操作,必须去机房记录新的IP.学了几天Shell之后想,是不是可以定时检测其IP的变化,一旦有 ...

  6. centos7下cups + samba共打印服务

    centos7下cups + samba共打印服务 2015年8月21日admin发表评论阅读评论   这个算是rhce课程的篇外篇,Samba除了提供文件共享外,也可以像windows下的共享一样提 ...

  7. TCP/IP协议三次握手_四次挥手

    TCP/IP协议 TCP是一种面向连接的端到端的可靠传输协议. TCP报头格式 三次握手的过程 一.客户端发送一个连接请求,发送一个随机数X,这时客户端的端口状态变为SYN_SENT状态. 二.服务端 ...

  8. IDEA 打包和导入 Jar 包

    Jar 包介绍 Jar 包 ( Java Archive,Java 归档文件) 是与平台无关的压缩文件格式,它允许将多个 Java 源文件编译生成的 class 文件(即字节码文件)打包成一个压缩文件 ...

  9. Spring IoC容器 XML 配置与加载

    IoC 容器 XML 配置文件 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=&qu ...

  10. Windows上能看朋友圈的微信来了 | 附下载地址

    昨天的时候,电脑端的微信提示更新就顺手更新了一下,更新完成后习惯性的点了下设置,纳尼,居然被灰到了测试版本? 带着好奇,赶快看了下更新了什么内容: 支持浏览朋友圈 "搜一搜"支持搜 ...