golang学习之defer

golang中的defer通常用于执行一些资源释放性操作,比如open/close、connect/disconnect、lock/unlock等,对defer理解主要记住以下三点:

1、defer 调用的函数参数的值 defer 被定义时就确定

举个例子,看如下代码:

i := 1
defer fmt.Println("Deferred print:", i)
i++
fmt.Println("Normal print:", i)

正确输出如下:

Normal print: 2
Deferred print: 1

这里的defer调用时,i的值是作为fmt.Println()函数的参数的,defer调用时,函数参数的值已经被上条赋值语句确定了为1,所以这里输出如此。

2、defer 函数内部所使用的变量的值需要在这个函数运行时才确定

这个其实也好理解,就是说如果变量i的值是作为defer函数体内的,那么该i值在return结束之前,才会被确定,举个例子:

func f1() (r int) {
    r = 1
    defer func() {
        r++
    }()
    return 2
}

执行测试:

fmt.Println(f1())

正确输出:3

这里解释下:

首先return并非原子操作,return 2可以拆分为如下两句代码:

r = 2
return

在r=2操作之后,defer中的r++便会执行,这时返回值r被修改为r++,所以实际返回值:3

3、defer 执行顺序为先进先出形式,类似于栈操作

这个如果理解了前两点的话,综合第三点便会知道多个defer共存时具体执行顺序。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏静默虚空的博客

[Java 进阶]异常

异常:程序在运行过程中发生由于硬件设备问题、软件设计错误等导致的程序异常事件。 世上没有百分之百完美的程序。程序总难免存在各式各样的问题。所以,程序中添加对于错...

1878
来自专栏大前端开发

ES6特性之:let和const

ES6之前,我们只有一种声明变量的方式:var,不能声明常量,如果我们有一些不变的值,比如一些固定的错误代码,我们可能会这样去声明,把它们当做常量来使用:

816
来自专栏FSociety

Oracle中字符串大小比较以及数据隐式转化

首先我们得明白在数据库中单引号是用来字符串引用的,不管是数字还是时间,当你用单引号引用起来之后,数据库就会将他当成字符串来对待。

882
来自专栏数据结构与算法

8758:2的幂次方表示

8758:2的幂次方表示 查看 提交 统计 提问 总时间限制: 1000ms 内存限制: 65536kB描述 任何一个正整数都可以用2的幂次方表示。例如:  ...

3576
来自专栏noteless

[七]基础数据类型之Float详解

Float 依然提供了根据基本类型float以及float的String形式构造

621
来自专栏面朝大海春暖花开

入住腾讯云+社区

对于的github基础代码https://github.com/chywx/JavaSE

321
来自专栏calmound

最小生成树判断唯一

题意:若最小生成树唯一则输出权值和,若不唯一输出Not Not Unique! 运用prim算法将最小生成树求出,然后在依次枚举删除最小生成树中的每一条边,判断...

3164
来自专栏我是攻城师

Java基础类String了解一下

当你路过一些商场或者地铁口的时候,有没有被千篇一律的"xx健身,了解一下" 所烦到。

2095
来自专栏水击三千

浅谈JavaScript的函数表达式(闭包)

  前文已经简单的介绍了函数的闭包。函数的闭包就是有权访问另一个函数作用域的函数,也就是函数内部又定义了一个函数。 1 var Super=function(n...

2135
来自专栏我是攻城师

Java基础类String了解一下

当你路过一些商场或者地铁口的时候,有没有被千篇一律的"xx健身,了解一下" 所烦到。

922

扫码关注云+社区