go-defer语句
Go语言中的defer语句也非常独特。
defer语句仅能被放置在函数或方法中。
它由关键字defer和一个调用表达式组成。
调用表达式所表示的既不能是对Go语言内建函数的调用
也不能是对Go语言标准库代码包unsafe中的那些函数的调用。
实际上,满足上述条件的调用表达式被称为表达式语句。
func readFile(path string) ([]byte, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()
return ioutil.ReadAll(file)
}
打开指定文件且未发现有错误发生之后,紧跟了一条defer语句。
其中携带的表达式语句表示的是对被打开文件的关闭操作。
注意,当这条defer语句被执行的时候,其中的这条表达式语句并不会被立即执行。
它的确切的执行时机是在其所属的函数(这里是readFile)的执行即将结束的那个时刻。
在readFile函数真正结束执行的前一刻,file.Close()才会被执行。
这也是defer语句被如此命名的原因。
语句defer file.Close()的含义是在打开文件并读取其内容后及时地关闭它。
该语句可以保证在readFile函数将结果返回给调用方之前,那个文件或目录一定会被关闭。
这实际上是一种非常便捷和有效的保险措施。
当一个函数中存在多个defer语句时,它们携带的表达式语句的执行顺序一定是它们的出现顺序的倒序。
下面的示例可以很好的证明这一点:
func deferIt() {
defer func() {
fmt.Print()
}()
defer func() {
fmt.Print()
}()
defer func() {
fmt.Print()
}()
fmt.Print()
}
deferIt函数的执行会使标准输出上打印出4321
defer携带的表达式语句代表的是对某个函数或方法的调用。这个调用可能会有参数传入。
如果代表传入参数的是一个表达式,那么在defer语句被执行的时候该表达式就会被求值了。
func deferIt3() {
f := func(i int) int {
fmt.Printf("%d ",i)
return i *
}
for i := ; i < ; i++ {
defer fmt.Printf("%d ", f(i))
}
}
它在被执行之后,标准输出上打印出1 。
defer携带的表达式语句代表的是对匿名函数的调用,那么我们就一定要非常警惕。请看下面的示例:
func deferIt4() {
for i := ; i < ; i++ {
defer func() {
fmt.Print(i)
}()
}
}
deferIt4函数在被执行之后标出输出上会出现5555,而不是4321
原因是defer语句携带的表达式语句中的那个匿名函数包含了对外部(确切地说,是该defer语句之外)的变量的使用。
注意,等到这个匿名函数要被执行(且会被执行4次)的时候,包含该defer语句的那条for语句已经执行完毕了。
此时的变量i的值已经变为了5。因此该匿名函数中的打印函数只会打印出5。
正确的用法是:把要使用的外部变量作为参数传入到匿名函数中。
修正后如下:
func deferIt4() {
for i := ; i < ; i++ {
defer func(n int) {
fmt.Print(n)
}(i)
}
}
go-defer语句的更多相关文章
- [Go] defer 语句
Go 还有一些特有的流程控制语句,其中一个就是 defer 语句.该语句用于延迟调用指定的函数,它只能出现在函数的内部,由 defer 关键字以及针对某个函数的调用表达式组成.这里被调用的函数称为 延 ...
- go语言之goto语句和函数和defer语句
1.goto关键字 import "fmt" func main() { for i := 0;i <11;i++{ if i == 2{ //关键字,goto跳转到某个位置 ...
- golang学习 ---defer语句
golang语言defer特性详解 defer语句是go语言提供的一种用于注册延迟调用的机制,它可以让函数在当前函数执行完毕后执行,是go语言中一种很有用的特性.由于它使用起来简单又方便,所以深得go ...
- go语言的defer语句
转: https://www.jianshu.com/p/5b0b36f398a2 ---------------------------------------------------------- ...
- Go语言中defer语句使用小结
defer是Go语言中的延迟执行语句,用来添加函数结束时执行的代码,常用于释放某些已分配的资源.关闭数据库连接.断开socket连接.解锁一个加锁的资源.Go语言机制担保一定会执行defer语句中的代 ...
- 探究 Go 语言 defer 语句的三种机制
Golang 的 1.13 版本 与 1.14 版本对 defer 进行了两次优化,使得 defer 的性能开销在大部分场景下都得到大幅降低,其中到底经历了什么原理? 这是因为这两个版本对 defer ...
- Go语言学习——函数二 defer语句
函数 package main import "fmt" // 函数:一段代码的封装 func f1(){ fmt.Println("Hello 中国!") } ...
- go defer 语句会延迟函数的执行直到上层函数返回。
defer code... 可以理解为 执行完当前defer所在的方法代码后执行defer 中的代码 常用在释放资源 比如 关闭文件 为防止忘记编写关闭代码 可以先写好 defer 各种释放资源 ...
- 【Go入门教程3】流程(if、goto、for、switch)和函数(多个返回值、变参、传值与传指针、defer、函数作为值/类型、Panic和Recover、main函数和init函数、import)
这小节我们要介绍Go里面的流程控制以及函数操作. 流程控制 流程控制在编程语言中是最伟大的发明了,因为有了它,你可以通过很简单的流程描述来表达很复杂的逻辑.Go中流程控制分三大类:条件判断,循环控制和 ...
- go:defer
defer:延迟. 假设有调用函数A.被调用函数B,其关系如下: func A(){//调用函数 ... defer B()//被调用函数 ... return//B将延迟到return前执行 } * ...
随机推荐
- MySQL实现Oracle rank()排序
一.Oracle写法介绍 MySQL5.7版本没有提供类似Oracle的分析函数,比如开窗函数over(...),oracle开窗函数over(...)使用的话一般是和order.partition ...
- EasySwoole+ElasticSearch打造 高性能 小视频服务系统
EasySwoole+ElasticSearch打造高性能小视频服务 第1章 课程概述 第2章 EasySwoole框架快速上手 第3章 性能测试 第4章 玩转高性能消息队列服务 第5章 小视频服务平 ...
- HTML文档简介
HTML简介 HTML标签 html文档标签: html源代码就好像word文档,有特殊的语法结构定义自己的功能. html文档标签 html标签,其下由两个主要节点标签head.body. head ...
- .net 和 java 技术对应关系
.net 和 java 技术对应关系 java 生态的优势早已人尽皆知,asp.net core 的生态也呈欣欣向荣之势.作为高级技术从业人,你不应该落下任何一门技术. 如果你正在将你的 java 知 ...
- windows环境下搭建python虚拟环境及离线移植
以python3.6为例 ①安装virtualenv: #pip安装之后在D:\Python36\Scripts目录下可以看到多了一个virtualenv.exe可执行文件pip install vi ...
- ajax发送PUT请求,使用HttpPutFormContentFilter过滤器接受办法
相信在使用ajax发送put请求时候,肯定遇到过后端数据无法被接受到的405错误. 为什么会遇到这个问题? 1.首先查看Tomcat源码 关于如何将数据封装到Request public class ...
- [Python]字典的简单用法
Python中的字典与现实中字典类似,从字典中可以找到“鱼”字:鱼类是体被骨鳞.以鳃呼吸.通过尾部和躯干部的摆动以及鳍的协调作用游泳和凭上下颌摄食的变温水生脊椎动物.类比到Python的字典中,把“鱼 ...
- Scrapy入门操作
一.安装Scrapy: 如果您还未安装,请参考https://www.cnblogs.com/dalyday/p/9277212.html 二.Scrapy基本配置 1.创建Scrapy程序 cd D ...
- 数据结构与算法(C/C++版)【数组】
第五章<数组> 一.概念 根据数组中存储的数据元素之间的逻辑关系,可以将数组分为 : 一维数组.二维数组.….n维数组.n维数组中,维数 n 的判断依据是:根据数组中为确定元素所在位置使用 ...
- PHPstorm出现的端口号错误问题(502)
咔咔咔-听好 PhpStorm的默认端口是63342,但是在浏览器会提示502错误. 同时Phpstorm右下角会报错:Please ensure that configured PHP Interp ...