1. Go语言中的defer语句也非常独特。
  2. defer语句仅能被放置在函数或方法中。
  3. 它由关键字defer和一个调用表达式组成。
  1. 调用表达式所表示的既不能是对Go语言内建函数的调用
  2. 也不能是对Go语言标准库代码包unsafe中的那些函数的调用。
  3. 实际上,满足上述条件的调用表达式被称为表达式语句。
  4. func readFile(path string) ([]byte, error) {
  5. file, err := os.Open(path)
  6. if err != nil {
  7. return nil, err
  8. }
  9. defer file.Close()
  10. return ioutil.ReadAll(file)
  11. }
  12. 打开指定文件且未发现有错误发生之后,紧跟了一条defer语句。
  13. 其中携带的表达式语句表示的是对被打开文件的关闭操作。
  14. 注意,当这条defer语句被执行的时候,其中的这条表达式语句并不会被立即执行。
  15. 它的确切的执行时机是在其所属的函数(这里是readFile)的执行即将结束的那个时刻。
  16. readFile函数真正结束执行的前一刻,file.Close()才会被执行。
  17. 这也是defer语句被如此命名的原因。
  1. 语句defer file.Close()的含义是在打开文件并读取其内容后及时地关闭它。
  2. 该语句可以保证在readFile函数将结果返回给调用方之前,那个文件或目录一定会被关闭。
  3. 这实际上是一种非常便捷和有效的保险措施。
  1. 当一个函数中存在多个defer语句时,它们携带的表达式语句的执行顺序一定是它们的出现顺序的倒序。
  2. 下面的示例可以很好的证明这一点:
  3. func deferIt() {
  4. defer func() {
  5. fmt.Print()
  6. }()
  7. defer func() {
  8. fmt.Print()
  9. }()
  10. defer func() {
  11. fmt.Print()
  12. }()
  13. fmt.Print()
  14. }
  15. deferIt函数的执行会使标准输出上打印出4321
  1. defer携带的表达式语句代表的是对某个函数或方法的调用。这个调用可能会有参数传入。
  2. 如果代表传入参数的是一个表达式,那么在defer语句被执行的时候该表达式就会被求值了。
  3. func deferIt3() {
  4. f := func(i int) int {
  5. fmt.Printf("%d ",i)
  6. return i *
  7. }
  8. for i := ; i < ; i++ {
  9. defer fmt.Printf("%d ", f(i))
  10. }
  11. }
  12. 它在被执行之后,标准输出上打印出1
  1. defer携带的表达式语句代表的是对匿名函数的调用,那么我们就一定要非常警惕。请看下面的示例:
  2. func deferIt4() {
  3. for i := ; i < ; i++ {
  4. defer func() {
  5. fmt.Print(i)
  6. }()
  7. }
  8. }
  9. deferIt4函数在被执行之后标出输出上会出现5555,而不是4321
  10. 原因是defer语句携带的表达式语句中的那个匿名函数包含了对外部(确切地说,是该defer语句之外)的变量的使用。
  11. 注意,等到这个匿名函数要被执行(且会被执行4次)的时候,包含该defer语句的那条for语句已经执行完毕了。
  12. 此时的变量i的值已经变为了5。因此该匿名函数中的打印函数只会打印出5
  1. 正确的用法是:把要使用的外部变量作为参数传入到匿名函数中。
  2. 修正后如下:
  3. func deferIt4() {
  4. for i := ; i < ; i++ {
  5. defer func(n int) {
  6. fmt.Print(n)
  7. }(i)
  8. }
  9. }

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. 15 (OC)* UIGesture

    前言 本文主要内容如下: 1. UIGestureRecognizer 属性.方法.代理和七个子类详解. 2. 讲讲 UIGestureRecognizer 和 UITouch 事件的关系. 3. 讲 ...

  2. Android嵌入式开发初学者的几个注意点

    一:首先你必须了解ARM平台 Android 移植与驱动核心开发,当然也可以是X86和其他的平台,不过其他平台的Android智能终端开发并不是很多. Android嵌入式智能操作系统是基于Linux ...

  3. Java匹马行天下之 Java国出了个Java——举国欢庆

    Java帝国的崛起 前言: 看庭前花开花落,宠辱不惊, 望天上云卷云舒,去留无意. 闹心的事儿,选择释怀: 纠缠的人儿,试着放下, 生活其实很美. 心若向阳,就无惧悲伤. 愿你明朗坦荡纵情豁达,有得有 ...

  4. Unity-遇到的问题小总结

    1. event trigger后面显示不了对应的方法 原因:我是直接把脚本拖拽进去的,这是没有实例化的,拖拽进去的应该是挂载这个脚本的GameObject就可以了 2.制作prefeb 将场景中的单 ...

  5. 配置文件my.cnf---配置信息注释大全

    在进行MySQL与CM+CHD之间的应用配置时,发现此前对于MySQL的配置含义过于模糊,所以将CM+CHD集群所涉及MySQL方面的配置含义进行抽取并加以注释,方便此后的配置和使用. 一.客户端设置 ...

  6. elasticsearch应用于产品列表

    package com.linkwee.web.service; import java.util.List; import com.linkwee.api.request.cim.ProductPa ...

  7. Ubuntu 启动zookeeper报错

    在启动zk客户端连接server时报错: 2019-03-30 23:06:24,915 [myid:localhost:2181] - INFO [main-SendThread(localhost ...

  8. 阿里云ESC服务器centos6.9使用及注意事项

    阿里云ESC服务器,配置低,但是足够新手尝试操作练习. 使用之前,注意事项: 选择操作系统 设置实例快照 安装终端工具 一,选择操作系统. 可以在购买服务器的时候进行选择系统盘,也可以在购买之后在实例 ...

  9. 如何让谷歌浏览器支持小于12px的字体

    CSS3有个新的属性transform,而我们用到的就是transform:scale() 书写一段代码 <body> <p>我是一个小于12PX的字体</p> & ...

  10. axios对put操作对Android的支持之坑

    ### 前段时间我做的一个手机端H5项目,需要发送一个put请求.因为ajax现在用的人有点少了,而且公司里边都是用的axios,所以我也是用的是axios做的请求. ### 再开发的时候测试都没有问 ...