defer以下几个特性,使用时需要关注下。

  • 即时的参数传递
  • 调用os.Exit()时defer不会被执行
  • defer与return的先后顺序

1.即时的参数传递

定义defer时传入的参数,是作为拷贝传递的。

也就是说,如果原来的变量值发生变化,不会影响传给defer的参数。

例子如下:

package main

import (
"fmt"
) func main(){ test() } func test() {
a := 0 defer func (i int) {
fmt.Println("in defer i:", i)
}(a) a += 1
fmt.Println("a:", a)
}

输出结果:

a: 1
in defer i: 0

可以看到,即使变量a发生变化,延迟执行时变量的值仍然是0,与定义defer时传入的值一样。

2.调用os.Exit()时defer不会被执行

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

package main

import (
"fmt"
"os"
) func main(){
fmt.Println("main start")
test()
} func test() () {
defer func () {
fmt.Println("in defer ... ")
}() os.Exit(0)
}

输出结果:

main start

defer定义的内容没有输出。

3.defer 与 return先后顺序

先来看两个例子:一个是返回匿名变量,一个是返回命名变量。

3.1 返回匿名变量

package main

import (
"fmt"
) func main(){
i := test()
fmt.Println("main i:", i)
} func test() int {
a := 0
defer func () {
a = 2
}() a = 1
return a
}

定义a为0, 接着修改为1,最后在defer中将a修改为2。

在main中返回的值仍然是1.

输出结果:

main i: 1

3.2 返回命名变量

package main

import (
"fmt"
) func main(){
i := test()
fmt.Println("main i:", i)
} func test() (a int) {
defer func () {
a = 2
}() a = 1
return a
}

defer中修改a为2,能够返回给调用方。

输出结果:

main i: 2

实际上,defer 函数的执行既不是在 return 之后也不是在 return 之前,而是 return 语句包含了对 defer 函数的调用,即 return 会被翻译成如下几条伪指令:

保存返回值到栈上(如果是匿名变量,需要定义变量并赋值)
调用defer函数(如果有defer函数,则调用并执行)
调整函数栈
retq指令返回(如果是匿名变量,直接返回新定义的变量,如果是命名变量,直接返回命名变量)

命名变量返回时,不会创建新的变量,所以defer的修改会返回去。

而匿名变量,会创建新的变量,defer中的修改,还是修改原来的变量,所以修改不能返回去。

4.参考

Defer, Panic, and Recover

https://juejin.im/post/5b9b4acde51d450e5071d51f

https://my.oschina.net/henrylee2cn/blog/505535

golang defer那些坑的更多相关文章

  1. Golang中的坑二

    Golang中的坑二 for ...range 最近两周用Golang做项目,编写web服务,两周时间写了大概五千行代码(业务代码加单元测试用例代码).用Go的感觉很爽,编码效率高,运行效率也不错,用 ...

  2. Golang 中的坑 一

    Golang 中的坑 短变量声明  Short variable declarations 考虑如下代码: package main import ( "errors" " ...

  3. Golang的防坑小技巧

    Golang的防坑小技巧 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 作为一名小白,在之前没有接触到编程的小伙伴,难免会踩到一些坑,比如说刚刚入门的时候你需要安装环境,学习Gol ...

  4. golang的defer踩坑汇总

    原文链接:http://www.zhoubotong.site/post/50.html defer语句用于延迟函数调用,每次会把一个函数压入栈中,函数返回前再把延迟的函数取出并执行.延迟函数可以有参 ...

  5. 初学者学习golang可能遇到的坑

    我也是个golang初学者,刚入门的话,有些"坑"还是不好发现的.如map只是定义了然后就拿来使用,变量的值覆盖等. 本来打算写一篇的,后面发现有人写的挺不错的,我就把里面的有些坑 ...

  6. golang defer 延后执行什么

    对于golang的defer,我们已经知道,defer定义的语句可以延后到函数返回时执行. 经常用在文件的关闭,锁的释放等场景中.而且defer定义的语句即使遇到panic也会执行.这样,可以执行必要 ...

  7. 『go成长之路』 defer 作用、典型用法以及多个defer调用顺序,附加defer避坑点,拿来吧你

    预习内容 defer 的作用有哪些? 多个 defer 的执行顺序是怎样的? defer,return,函数返回值 三者之间的执行顺序 defer的作用 go中的defer是延迟函数,一般是用于释放资 ...

  8. golang的哪些坑爷事: package实践

    在golang中package是个困惑的概念, 特别是package还可以与folder不同名, 委实让我恶心了一把. 关于golang的package的最佳实践: package is folder ...

  9. golang defer的使用

    defer一般用于在函数结束时执行必要的处理工作.例如,关闭文件描述符,关闭网络连接等等. 函数中可以定义多个defer,执行的时候按照先进后出的顺序. defer定义的语句,即使遇到panic,也会 ...

随机推荐

  1. vue项目打包后在IE浏览器报错,页面显示空白

    之前写一个项目,一直放在谷歌浏览器调试测试,到尾声时放到IE浏览器结果直接白屏,页面打不开 找了网上的方法,加了babel-polyfill插件后还是不行,后来排查发现是打包插件出了问题,因为用的项目 ...

  2. hive元数据库理解

    在hive2.1.1 里面一共有59张表 表1 VERSION ; version表存hive的版本信息,该表中数据只有一条,如果存在多条,会造成hive启动不起来. 表2  DBS select * ...

  3. IDEA修改Maven全局配置

    在使用过程中发现,IDEA每次新建一个Project ,这个maven配置都会初始化默认的. 这里需要设置下全局配置: File -> Other Settings -> Settings ...

  4. git配置ssh秘钥(公钥以及私钥)linux

    本文默认已经安装git,并有github或者gitlab账号 git在linux下安装参考:https://www.cnblogs.com/lz0925/p/10791147.html 在Linux中 ...

  5. LINUX修改path环境变量

    PATH用作运行某个命令的时候,本地查找不到某个命令或文件,会到这个声明的目录中去查找. 例如一般设定java的时候为了在任何目录下都可以运行bin文件夹下的命令.就将java的bin目录声明到pat ...

  6. 韦东山嵌入式Linux学习笔记04--点亮开发板的一个LED灯

    搜索开发板原理图LED的走线           LED8是网线接口的指示灯. 在这里我们尝试用汇编代码控制D10, 也就是LED1,它连接到EINT4/GPF4,读取芯片手册 有原理图可知,如果需要 ...

  7. git用ssh方式下载和提交代码

    之前git上传下载代码都是用的http方式,但是今天遇到个大文件上传的时候,http方式上传超出大小限制了413 request entity too large,所以改成了用ssh方式上传,简单记录 ...

  8. java8学习之流的短路与并发流

    并发流: 从api的角度来看,其实跟咱们之前一直在用的stream()方式差不多,但是底层是有明显的不同,所以这里初步先对并发流有一个基本的认识, 说到串行与并行,最直观的感受就是效率的不同,所以下面 ...

  9. LCA-tarjan understand 2

    下面是一个最基础的LCA题目    http://poj.org/problem?id=1330 赤裸裸的 题意 输入cas 后  有cas组数据 输入 n   再输入n-1 条边    之后输入x ...

  10. maven地址配置为阿里maven仓库,附ali maven官方指南链接

    一.参考链接 官方指南 链接地址:https://help.aliyun.com/document_detail/102512.html?spm=a2c40.aliyun_maven_repo.0.0 ...