GO语言学习笔记5-defer的使用
什么是defer
defer是Go语言提供的一种用于注册延迟调用的机制:让函数或语句可以在当前函数执行完毕后(包括通过return正常结束或者panic导致的异常结束)执行。
defer的应用场景
defer语句通常用于一些成对操作的场景:打开连接/关闭连接;加锁/释放锁;打开文件/关闭文件等。
defer的原理
defer语句并不会马上执行,而是会进入一个栈,函数return前,会按先进后出(FILO)的顺序执行。也就是说最先被定义的defer语句最后执行。先进后出的原因是后面定义的函数可能会依赖前面的资源,自然要先执行;否则,如果前面先执行,那后面函数的依赖就没有了。
defer的引用方式
defer语句定义时,对外部变量的引用有如下两种方式:
1.作为函数参数和作为闭包引用。作为函数参数,则在defer定义时就把值传递给defer,并被缓存起来。
2.作为闭包引用的话,则会在defer函数真正调用时根据整个上下文确定当前的值。
defer的踩坑点
避免踩坑的关键是要理解这条语句:
return xxx
这条语句经过编译之后,会变成了三条指令:
1. 返回值 = xxx
2. 调用defer函数
3. 空的return
第1,3 步才是return 语句真正的命令,第2步是 defer的定义语句,这里就有可能会操作返回值。
代码示例
示例1:
func f() (r int) {
defer func() {
r++
}()
return 0
}
拆解过程:
func f() (r int) {
// 1.赋值
r = 0
// 2.闭包引用,返回值被修改
defer func() {
r++
}()
// 3.空的return
return
}
由于defer是闭包引用,返回值被修改,所以f()返回 1。
示例2:
func f() (r int) {
t := 5
defer func() {
t = t + 5
}()
return t
}
拆解过程:
func f() (r int) {
t := 5
// 1.赋值
r = t
// 2.闭包引用,但是没有修改返回值r
defer func() {
t = t + 5
}()
// 3.空的return
return
}
由于第2步未涉及返回值r的操作,所以返回5。
示例3:
func f() (r int) {
defer func(r int) {
r = r + 5
}(r)
return 1
}
拆解过程:
func f() (r int) {
// 1.赋值
r = 1
// 2.r作为函数参数,不会修改要返回的那个r值
defer func(r int) {
r = r + 5
}(r)
// 3.空的return
return
}
由于第2步中r是作为函数参数使用,只是一份拷贝,defer语句里面的r和外面的r其实是两个变量,里面变量r的改变不会影响外层变量r,所以不是返回6,而是返回1。
个人主页:
GO语言学习笔记5-defer的使用的更多相关文章
- GO语言学习笔记(一)
GO语言学习笔记 1.数组切片slice:可动态增长的数组 2.错误处理流程关键字:defer panic recover 3.变量的初始化:以下效果一样 `var a int = 10` `var ...
- Go语言学习笔记(1)——顺序编程
Go语言学习笔记这一堆主要是<Go语言编程>(人民邮电出版社)的读书笔记.中间会穿插一些零碎的点,比如源码学习之类的.大概就是这样吧. 1. 顺序编程 1.1 变量 变量的声明: var ...
- HTML语言学习笔记(会更新)
# HTML语言学习笔记(会更新) 一个html文件是由一系列的元素和标签组成的. 标签: 1.<html></html> 表示该文件为超文本标记语言(HTML)编写的.成对出 ...
- 2017-04-21周C语言学习笔记
C语言学习笔记:... --------------------------------- C语言学习笔记:学习程度的高低取决于.自学能力的高低.有的时候生活就是这样的.聪明的人有时候需要.用笨的方法 ...
- 2017-05-4-C语言学习笔记
C语言学习笔记... ------------------------------------ Hello C语言:什么是程序:程序是指:完成某件事的既定方式和过程.计算机中的程序是指:为了让计算机执 ...
- Haskell语言学习笔记(88)语言扩展(1)
ExistentialQuantification {-# LANGUAGE ExistentialQuantification #-} 存在类型专用的语言扩展 Haskell语言学习笔记(73)Ex ...
- Go语言学习笔记十三: Map集合
Go语言学习笔记十三: Map集合 Map在每种语言中基本都有,Java中是属于集合类Map,其包括HashMap, TreeMap等.而Python语言直接就属于一种类型,写法上比Java还简单. ...
- Go语言学习笔记十二: 范围(Range)
Go语言学习笔记十二: 范围(Range) rang这个关键字主要用来遍历数组,切片,通道或Map.在数组和切片中返回索引值,在Map中返回key. 这个特别像python的方式.不过写法上比较怪异使 ...
- Go语言学习笔记十一: 切片(slice)
Go语言学习笔记十一: 切片(slice) 切片这个概念我是从python语言中学到的,当时感觉这个东西真的比较好用.不像java语言写起来就比较繁琐.不过我觉得未来java语法也会支持的. 定义切片 ...
- Go语言学习笔记十: 结构体
Go语言学习笔记十: 结构体 Go语言的结构体语法和C语言类似.而结构体这个概念就类似高级语言Java中的类. 结构体定义 结构体有两个关键字type和struct,中间夹着一个结构体名称.大括号里面 ...
随机推荐
- CodeSmith 找不到请求的 .Net Framework Data Provider
连接数据库时候报标题的错误解决方案 安装mysql-connector-net-6.8.7.msi,下载地址:http://dev.mysql.com/downloads/connector/net/ ...
- javascript 数据类型 undefined 和null
数据类型 undefind null boolean number string object type of 功能:检测变量类型 语法:type of 变量或 type of (变量) consol ...
- SheetJS js-xlsx 的使用, exceljs
js-xlsx 官方文档:https://sheetjs.gitbooks.io/docs/#sheetjs-js-xlsx npm xlsx地址:https://www.npmjs.com/pack ...
- [转帖]56核Xeon Platinum 9200现身 - 英特尔有史以来最大的CPU封装
56核Xeon Platinum 9200现身 - 英特尔有史以来最大的CPU封装 https://www.cnbeta.com/articles/tech/835271.htm 当英特尔宣布上周正式 ...
- (2.2)【转】mysql的SQL笔记
一千行 MySQL 详细学习笔记 IT技术思维 4月1日 ↑↑↑点上方蓝字关注并星标⭐「IT技术思维」 一起培养顶尖技术思维 作者:格物 原文链接:https://shockerli.net/post ...
- MyBatis Mapper XML 详解
MyBatis Mapper XML 详解 MyBatis 真正的力量是在映射语句中.这里是奇迹发生的地方.对于所有的力量,SQL 映射的 XML 文件是相当的简单.当然如果你将它们和对等功能的 JD ...
- P1216数字三角形
这是USACO的一道记忆化搜索题,还记得原来学搜索就是被此所困. 给定n深的数,第i层有i个节点,存储有一个数字,询问从第一层走到最后一层所经过节点上数字和的最大值.我们很容易想到枚举所有路径来计算最 ...
- javaweb:关于HttpServletRequest介绍 (转)
出处:https://www.cnblogs.com/xdp-gacl/p/3798347.html 一.HttpServletRequest介绍 HttpServletRequest对象代表客户端的 ...
- 使用Idea部署SSM项目后,访问路径为url:8080/项目名_war_exploded的解决方案
在tomcat配置页的Deployment下,修改Application context为/,即可直接使用url:8080访问项目主页.
- P4304 [TJOI2013]攻击装置
传送门 看到棋盘先黑白染色冷静一下 然后发现...攻击的时候同种颜色不会相互攻击 这样就是个网络流经典套路了,关于这个套路我以前好像写过几题,那边有解释一下:传送门 #include<iostr ...