A "defer" statement invokes a function whose execution is deferred to the moment the surrounding function returns, either because the surrounding function executed a return statement, reached the end of its function body, or because the corresponding goroutine is panicking.

defer语句会在以下几种情况下被执行:

a. 函数执行return语句
b. 执行到函数体结尾
c. goroutine panic之前
 

Each time a "defer" statement executes, the function value and parameters to the call are evaluated as usual and saved anew but the actual function is not invoked. Instead, deferred functions are invoked immediately before the surrounding function returns, in the reverse order they were deferred. That is, if the surrounding function returns through an explicit return statement, deferred functions are executed after any result parameters are set by that return statement but before the function returns to its caller. If a deferred function value evaluates to nil, execution panics when the function is invoked, not when the "defer" statement is executed.

每次执行defer语句时,会将其定义的函数和参数保存在一个栈中,但是定义的函数并不会被执行。但是,在外层函数退出之前,defer函数会按照定义的顺序逆序执行。如果外层函数通过显示return语句返回,则defer定义的函数是在设置结果参数之后,返回调用方之前执行。如果defer要执行的函数为nil,则会在定义的函数调用时产生panic,而不是defer语句执行时。

 

1. defer原理分析

a. 多个defer执行顺序

当一个函数中存在多个defer语句时,函数返回之前会按照defer定义的顺序逆序执行,也就是说最先注册的defer函数最后执行。

b. defer语句执行时拷贝时机

当defer语句执行时,会将当前时刻的函数值和函数参数进行注册。注册完成之后再次修改函数值和函数参数将不会生效。

c. return & defer

return x :返回值 = x   +   RET指令

defer 原理 :返回值 = x + defer语句 + RET指令

d. defer & 闭包

func main() {
  x := 1
  defer func() {
    fmt.Println(x)      // 2
  }()
  x++
}

上例中的 func()是一个闭包,闭包的变量本质是对上层变量的引用。

type Closure struct {

  F func()

  x *int

}

相比于直接调用函数,延迟调用需要花费更大的代价。这其中包括注册、调用等操作,还有额外的缓存开销。

对于性能要求高且压力大的算法,应该尽量避免延迟调用。

最新文章

  1. python code
  2. 2016 华南师大ACM校赛 SCNUCPC 非官方题解
  3. MFC如何读取XML
  4. acm入门 杭电1001题 有关溢出的考虑
  5. windows phone 水印TextBox
  6. jquery 实现类似于弹幕效果
  7. js如何判断手机机型
  8. 蛋疼的vs
  9. UITextField中文搜索
  10. UVALive 4043 Ants 蚂蚁(二分图最佳完美匹配,KM算法)
  11. [转]ASP.NET 页生命周期概述
  12. UVA 1001 Say Cheese 奶酪里的老鼠(最短路,floyd)
  13. 库函数strlen源码重现及注意问题
  14. POJ 1410 Intersection(线段相交&&推断点在矩形内&&坑爹)
  15. AFNetworking 动态修改acceptableContentTypes 设置ContentType
  16. vim操作备忘录
  17. App测试的策略
  18. DL_WITH_PY系统学习(第2章)
  19. html5 canvas旋转+缩放
  20. Arduino驱动无源蜂鸣器发声

热门文章

  1. Mybatis中Log4j日志的使用
  2. mmap代替通用IO读取文件数据(curious)
  3. leetcode210.拓扑排序
  4. 我们如何监视所有 Spring Boot 微服务?
  5. mybatis中jdbcType和javaType
  6. 说说finally和final的区别
  7. PACT 在微服务架构中的用途是什么?
  8. Netty + Spring + ZooKeeper搭建轻量级RPC框架
  9. 【静态页面架构】CSS之定位
  10. ES6-11学习笔记--深拷贝与浅拷贝