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

}

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

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

defer综合的更多相关文章

  1. 前端面试题集锦及答案解析--HTML、 HTTP、web综合问题

    前端需要注意哪些SEO 合理的title.description.keywords:搜索对着三项的权重逐个减小,title值强调重点即可,重要关键词出现不要超过2次,而且要靠前,不同页面title要有 ...

  2. 浏览器环境下JavaScript脚本加载与执行探析之defer与async特性

    defer和async特性相信是很多JavaScript开发者"熟悉而又不熟悉"的两个特性,从字面上来看,二者的功能很好理解,分别是"延迟脚本"和"异 ...

  3. golang基础--细说defer

    defer 匿名函数特性 执行方式类似其它语言中的析构函数,在函数体执行结束后按照调用顺序的相反顺序逐个执行 //执行顺序相反 package main import "fmt" ...

  4. golang学习之defer

    golang中的defer通常用于执行一些资源释放性操作,比如open/close.connect/disconnect.lock/unlock等,对defer理解主要记住以下三点: 1.defer ...

  5. AEAI DP V3.6.0 升级说明,开源综合应用开发平台

    AEAI DP综合应用开发平台是一款扩展开发工具,专门用于开发MIS类的Java Web应用,本次发版的AEAI DP_v3.6.0版本为AEAI DP _v3.5.0版本的升级版本,该产品现已开源并 ...

  6. H5+JS+CSS3 综合应用

    慕课网新教程H5+JS+CSS3 实现的七夕言情主题效果已经出炉了 从设计到实现到录制与编写用了快1个月的时间,说真的这个案例是慕课定制的,我之前也没有系统的做过这样的一个效果,在实现的时候自己也重新 ...

  7. 浅谈Angular的 $q, defer, promise

    浅谈Angular的 $q, defer, promise 时间 2016-01-13 00:28:00  博客园-原创精华区 原文  http://www.cnblogs.com/big-snow/ ...

  8. javascript的defer和async的区别。

    我们常用的script标签,有两个和性能.js文件下载执行相关的属性:defer和async defer的含义[摘自https://developer.mozilla.org/En/HTML/Elem ...

  9. script标签中defer和async属性的区别

    这篇文章来源于JS高级程序设计第三版中关于script标签的介绍,结合查阅的资料写下的学习笔记. 向html页面中插入javascript代码的主要方法就是通过script标签.其中包括两种形式,第一 ...

随机推荐

  1. 女朋友问我深浅copy到底是什么?

    深浅拷贝 列表存放值的时候,是先申请一块内存空间,存放索引和内存地址的对应关系,其实通俗的来说列表内不存真正的值,是一种间接存放的对应关系: 列表内存不可变类型的数据 就比如说,如果现在将L列表索引0 ...

  2. Flash XSS

    示例: 创建一个测试flash,代码如下,导出swf文件 //取m参数 var m=_root.m; //取showInfo参数 var showInfo=_root.showInfo; //调用ht ...

  3. Kafka03--Kafka消费者使用方式

    前言 与生产者客户端一样,消费者端也由最初的scala版本过渡到现在的Java版本. 正常的消费者逻辑需要以下4个步骤: KafkaConsumer的客户端参数配置和对应实例: 订阅主题 拉取消息并消 ...

  4. 如何实现 Spring Boot 应用程序的安全性?

    为了实现 Spring Boot 的安全性,我们使用 spring-boot-starter-security 依赖项,并且必须添加安全配置.它只需要很少的代码.配置类将必须扩展WebSecurity ...

  5. 匿名内部类编译生成的class文件

    一.问题描述 跳槽到的新公司,相比原来的公司,软件开发非常不规范,经常各种坑.项目部署到生产现场之后,出现问题,我在修改之后编译生成class文件,然后将class文件发给现场的技术支持,技术支持将c ...

  6. C printf格式化输出

    转载:https://blog.csdn.net/wucz122140729/article/details/98434702 格式化输出       格式化输出的函数有printf.sprintf和 ...

  7. 如何将 memcached 中 item 批量导入导出?

    您不应该这样做!Memcached 是一个非阻塞的服务器.任何可能导致 memcached 暂停或瞬时拒绝服务的操作都应该值得深思熟虑.向 memcached 中批量导入数据往往不是您真正想要的!想象 ...

  8. springMVC和struts2的区别有哪些?

    (1)springmvc的入口是一个servlet即前端控制器(DispatchServlet),而struts2入口是一个filter过虑器(StrutsPrepareAndExecuteFilte ...

  9. spring-boot-learning 日志相关

    sprint-boot 日志   市面上的日志框架: JUL.JCL.Jboss-logging.logback.log4j.log4j2.slf4j.... SpringBoot:底层是Spring ...

  10. 学习zabbix(三)

    前言: 学习zabbix之前,不得不了解的是SNMP协议 SNMP:简单网络管理协议(Simple Network Protocol) Snmp由两部分组成,监控端和被监控端 监控模式: 主动模式:N ...