我是谁

defer - 顾名思义翻译过来叫 延迟, 所以我们通常称呼 defer func() 这样 defer 后面紧跟的函数为 延迟函数.

作者注: 不过从实际应用来讲, 延迟函数通常用来做一些函数最终返回前的一些收尾工作, 所以称呼为收尾函数其实更贴切.

三围几何

defer 有其独特的一面, 了解其个性, 才能更好的下手...对待妹纸, 应该也是这么个理

延迟性

顾名思义, 既然叫延迟函数, 那么肯定具备延迟性.

我们来看看怎么个延迟法, defer_defer.go

// defer_defer.go
package main import (
"fmt"
) func main() {
foo()
} func foo() {
fmt.Println(1)
defer fmt.Println(2)
fmt.Println(3)
} // go run defer_defer.go
// 1
// 3
// 2

可以看到 defer 定义的延迟函数最后才执行.

再来个例子, 如果一个函数内出现多个延迟函数, 延迟函数的执行顺序又是怎么样的呢?

defer_filo.go

// defer_filo.go
package main import (
"fmt"
) func main() {
foo()
} func foo() {
defer fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
} // go run defer_filo.go
// 3
// 2
// 1

可以看到先定义的延迟函数后执行, 后定义的延迟函数先执行, 符合栈 (stack) 的先进后出 (FILO) 原则.

影响性

直接看代码, defer_impact.go

// defer_impact.go
package main import (
"fmt"
) func main() {
fmt.Println(foo())
} func foo() (result int) {
defer func() {
result++
}()
return 0
} // go run defer_defer.go
// 1

结果是不是跟想象有点不一样? 上述 foo() 可以改写为下:

func foo() (result int) {
result = 0
result++
return
}

go 中的 return 语句不是原子操作.

go 中 return 语句的操作过程为:

  • 设置返回值
  • 执行延迟函数
  • 真正 return

所以延迟函数会影响主函数的返回值, 当然还要区分具名返回值/匿名返回值, 后话再说.

确定性

延迟函数的参数值, 在延迟函数首次出现时就确定了, 不受后续操作的影响.

我们来个例子: defer_parameters.go

// defer_parameters.go
package main import (
"fmt"
) func main() {
foo()
} func foo() {
number := 1
defer fmt.Println(number)
number = 2
return
} // go run defer_parameters.go
// 1

能做啥

  • 打开数据链接, 要记得关闭, 可以用 defer
  • 操作完内存资源, 要记得释放, 可以用 defer
  • 想改变主函数的具名返回值, 可以用 defer - 通常不会这么干
  • 想奇淫技巧, 可以用 defer - 偶尔 show 偶尔爽, 一直 show 一直爽
  • 想搞事情, 可以用 defer - 请自行确保生命和财产安全
  • ...

参考:

go 关键字之 defer的更多相关文章

  1. Go语言 关键字:defer

    defer和go一样都是Go语言提供的关键字.defer用于资源的释放,会在函数返回之前进行调用.一般采用如下模式: f,err := os.Open(filename) if err != nil ...

  2. go语言defer关键字背后的实现,语法,用法

    原文: https://tiancaiamao.gitbooks.io/go-internals/content/zh/03.4.html ------------------------------ ...

  3. go 学习笔记之咬文嚼字带你弄清楚 defer 延迟函数

    温故知新不忘延迟基础 A "defer" statement invokes a function whose execution is deferred to the momen ...

  4. golang中defer的正确使用方式(源自深入解析go)

    3.4 defer关键字 defer和go一样都是Go语言提供的关键字.defer用于资源的释放,会在函数返回之前进行调用.一般采用如下模式: f,err := os.Open(filename) i ...

  5. Javascript是单线程的深入分析

    本来想总结一下的,网上却发现有人已经解释的很清楚了,特转过来. 这也解释了为什么在用自动化测试工具来运行dumrendtree时设定的超时和测试case设定的超时的关联性. 面试的时候发现99%的童鞋 ...

  6. 从C++到GO

    从C++到GO 刚开始接触Go语言,看了两本Go语言的书,从c++开发者的角度来看看go语言的新特性,说下自己感触较深的几点: 并发编程 Go语言层面支持协程,将并发业务逻辑从异步转为同步,大幅提高开 ...

  7. 深入分析 Javascript 单线程

    面试的时候发现99%的童鞋不理解为什么JavaScript是单线程的却能让AJAX异步发送和回调请求,还有setTimeout也看起来像是多线程的?还有non-blocking IO, event l ...

  8. go语法之一

    Go语法: Go语言要求public的变量必须以 大写字母开头,private变量则以小写字母开头,这种做法不仅免除了public.private关键字,更重要的是统一了命名风格. Go语言对{  } ...

  9. 掌握一门语言Go

    摘要:Go语言的优势不必多说,通过本篇文章,让我们花时间来掌握一门外语,Let's Go! 关键字:Go语言,闭包,基本语法,函数与方法,指针,slice,defer,channel,goroutin ...

随机推荐

  1. idea启动或install时报错:There are test failures,如何跳过测试?

    用idea  install项目时失败,报这样的错: [INFO] BUILD FAILURE [INFO] --------------------------------------------- ...

  2. Selenium 警告框处理

    警告框分三种类型: alert:显示带有一条指定消息和一个 OK 按钮的警告框. confirm:显示一个带有指定消息和 OK 及取消按钮的对话框. prompt:显示可提示用户进行输入的对话框. 我 ...

  3. 从零开始,编写简单的课程信息管理系统(使用jsp+servlet+javabean架构)

    一.相关的软件下载和环境配置 1.下载并配置JDK. 2.下载eclipse. 3.下载并配置apache-tomcat(服务器). 4.下载MySQL(数据库). 5.下载Navicat for M ...

  4. 二次封装axios,根据参数来实现多个请求多次拦截

    1. 新建 axiosTool.js 文件,设置请求拦截和处理的逻辑 import Vue from 'vue' import axios from 'axios' //取消请求 let Cancel ...

  5. 图的深度优先搜索(DFS)和广度优先搜索(BFS)算法

    深度优先(DFS) 深度优先遍历,从初始访问结点出发,我们知道初始访问结点可能有多个邻接结点,深度优先遍历的策略就是首先访问第一个邻接结点,然后再以这个被访问的邻接结点作为初始结点,访问它的第一个邻接 ...

  6. spring 中的一些注解功能--不定更新

    1@Qualifier注解? 下面的示例将会在Customer的person属性中自动装配Person的值. public class Customer { @Autowired private Pe ...

  7. HTM基础之HTML标签

    HTML(超文本标记语言) html代码实际上就是一套能够被浏览器所识别的规则代码,由一个个标签组成.html代码就是一大长串字符串,而这种字符串的格式正好能够被浏览器所识别,也就有了我们的WEB页面 ...

  8. 阶段3 1.Mybatis_07.Mybatis的连接池及事务_5 mybatis中使用poolead配置连接的原理分析

    idelConnection是空闲的链接 idelConnection就是ArrayList的数组 如果没有空闲的就new一个 新的connection 一个空闲池,一个活动的池,一个链接过来.空闲池 ...

  9. django的url的name参数的意义及view中reverse

    Templates的链接地址都是根据urlpatterns定义的地址,拼凑成地址字符串,很难看,而且Templates里拼凑成的地址,随着页面的增加而不断增加,一旦在urlpatterns里的某个地址 ...

  10. Java面试题集(116-135)

    Java程序员面试题集(116-135) 摘要:这一部分讲解基于Java的Web开发相关面试题,即便在Java走向没落的当下,基于Java的Web开发因为拥有非常成熟的解决方案,仍然被广泛应用.不管你 ...