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语句的更多相关文章

  1. [Go] defer 语句

    Go 还有一些特有的流程控制语句,其中一个就是 defer 语句.该语句用于延迟调用指定的函数,它只能出现在函数的内部,由 defer 关键字以及针对某个函数的调用表达式组成.这里被调用的函数称为 延 ...

  2. go语言之goto语句和函数和defer语句

    1.goto关键字 import "fmt" func main() { for i := 0;i <11;i++{ if i == 2{ //关键字,goto跳转到某个位置 ...

  3. golang学习 ---defer语句

    golang语言defer特性详解 defer语句是go语言提供的一种用于注册延迟调用的机制,它可以让函数在当前函数执行完毕后执行,是go语言中一种很有用的特性.由于它使用起来简单又方便,所以深得go ...

  4. go语言的defer语句

    转: https://www.jianshu.com/p/5b0b36f398a2 ---------------------------------------------------------- ...

  5. Go语言中defer语句使用小结

    defer是Go语言中的延迟执行语句,用来添加函数结束时执行的代码,常用于释放某些已分配的资源.关闭数据库连接.断开socket连接.解锁一个加锁的资源.Go语言机制担保一定会执行defer语句中的代 ...

  6. 探究 Go 语言 defer 语句的三种机制

    Golang 的 1.13 版本 与 1.14 版本对 defer 进行了两次优化,使得 defer 的性能开销在大部分场景下都得到大幅降低,其中到底经历了什么原理? 这是因为这两个版本对 defer ...

  7. Go语言学习——函数二 defer语句

    函数 package main import "fmt" // 函数:一段代码的封装 func f1(){ fmt.Println("Hello 中国!") } ...

  8. go defer 语句会延迟函数的执行直到上层函数返回。

    defer code... 可以理解为 执行完当前defer所在的方法代码后执行defer 中的代码 常用在释放资源 比如 关闭文件 为防止忘记编写关闭代码 可以先写好   defer  各种释放资源 ...

  9. 【Go入门教程3】流程(if、goto、for、switch)和函数(多个返回值、变参、传值与传指针、defer、函数作为值/类型、Panic和Recover、main函数和init函数、import)

    这小节我们要介绍Go里面的流程控制以及函数操作. 流程控制 流程控制在编程语言中是最伟大的发明了,因为有了它,你可以通过很简单的流程描述来表达很复杂的逻辑.Go中流程控制分三大类:条件判断,循环控制和 ...

  10. go:defer

    defer:延迟. 假设有调用函数A.被调用函数B,其关系如下: func A(){//调用函数 ... defer B()//被调用函数 ... return//B将延迟到return前执行 } * ...

随机推荐

  1. 降低 80% 的读写响应延迟!我们测评了 etcd 3.4 新特性(内含读写发展史)

    作者 | 陈洁(墨封)  阿里云开发工程师 导读:etcd 作为 K8s 集群中的存储组件,读写性能方面会受到很多压力,而 etcd 3.4 中的新特性将有效缓解压力,本文将从 etcd 数据读写机制 ...

  2. ZK Watcher 的原理和实现

    什么是 ZK Watcher 基于 ZK 的应用程序的一个常见需求是需要知道 ZK 集合的状态.为了达到这个目的,一种方法是 ZK 客户端定时轮询 ZK 集合,检查系统状态是否发生了变化.然而,轮询并 ...

  3. linux 假死分析

    所谓假死,就是能ping通,但是ssh不上去:任何其他操作也都没反应,包括上面部署的apache也打不开页面. 作为一个多任务操作系统,要把系统忙死,忙到ssh都连不上去,也不是那么容易的.尤其是现在 ...

  4. Elasticsearch(10) --- 内置分词器、中文分词器

    Elasticsearch(10) --- 内置分词器.中文分词器 这篇博客主要讲:分词器概念.ES内置分词器.ES中文分词器. 一.分词器概念 1.Analysis 和 Analyzer Analy ...

  5. 视频转成在github的readme中展示项目的gif动图

    本文中涉及的FastStone Capture和FFmpeg两个软件的百度网盘链接: 链接:https://pan.baidu.com/s/1D5LO9Qmjl-vwJZfnbAloyQ 提取码:56 ...

  6. sql server 中常用修改列 ,创建主外键操作

    表结构 CREATE TABLE [staff] ( [id] [varchar](50) NOT NUL L, [name] [varchar](50) NOT NULL, [password] [ ...

  7. WordPress后台地址路径修改方法

    用过WordPress后台的,其实都知道http://域名目录/wp-login.php就是登录地址,如果这时候使用暴力破解,很可能破解密码(这就有些想象力了),下面芝麻带你看看如何自定义美观的地址. ...

  8. 【SQL server基础】手动创建数据库和表格

    use master go if exists(select * from sysdatabases where name='learning') drop database learning go ...

  9. CSS3相关编码规范

    一.CSS书写顺序 1.位置属性(position, top, right, z-index, display, float等)2.大小(width, height, padding, margin) ...

  10. String 用法 简单API

    明天天梯赛选拔,怕不是STl忘到姥姥家去了,赶紧复习一下 构造str string s = "fuckyouRMA"; string s1(s, 2); de(s1); strin ...