defer用于向当前函数注册稍后执行的函数调用。这些调用被称作延迟调用,它们直到当前函数执行结束前才被执行,常用于资源释放、错误处理等操作

func main() {f, err := os.Open("/test.txt")if err != nil {fmt.Println("os.Open err:", err)return}defer f.Close()   // 仅注册,直到main退出前才执行
}

延迟调用注册的是调用,不是函数,需提供执行所需参数。参数值在注册时被赋值并缓存起来,如此状态敏感,可改用指针或闭包。延迟函数返回值会被抛弃

func main() {x, y := 1, 2defer func(a int) {println("defer x, y = ", a, y) // 为闭包引用}(x) // 注册时复制调用参数x += 100 // 对x的修改,不会影响延迟调用y += 200println(x, y)
}

输出:

101 202
defer x, y = 1 202

多个延迟注册按FILO次序执行

func main() {defer println("a")defer println("b")
}

输出:

b
a

编译器通过在ret指令前插入指令来实现延迟调用执行,而return和panic语句都会终止 当前函数流程,弓I发延迟调用°return不是ret,它会更新返回值

func main() {println("test:", test())
}func test() (z int) {defer func() {println("defer:", z)z += 100 // 修改命名返回值}()return 100 // 实际执行次序:z = 100, call defer, ret
}

输出:

defer: 100
test: 200

千万记住,延迟调用是在函数结束时才被执行。不合理的使用方式会浪费更多的资源,甚 至造成逻辑错误。

案例:循环处理多个日志文件,defer导致文件关闭时机延长

func main() {for i := 0; i < 10000; i++ {path := fmt.Sprintf("./log/%d.txt", i)f, err := os.Open(path)if err != nil {log.Println(err)continue}defer f.Close()// 这个关闭操作在main函数结束时才会执行,而不是当前循环。// 延长了逻辑结束时间和f生命周期,平白多消耗了内存等资源。 // 编译器也会提醒:可能发生资源泄漏,在 'for' 循环中调用 'defer' }
}

应该直接调用,或重构为函数,让循环和处理算法分离

func main() {//日志处理算法。do := func(n int) {path := fmt.Sprintf("./log/%d.txt", n)f, err := os.Open(path)if err != nil {log.Println(err)return}defer f.Close()    // 该延迟调用在此匿名函数结束时执行,而非main}for i := 0; i < 10000; i++ {do(i)}
}

相比直接用CALL指令调用函数,延迟调用则需花费更大代价。这其中包括注册、调用等 操作,还有额外的缓存开销。相差几倍的结果足以引起重视。尤其是那些性能要求高且压力大的算法,应避免使用

Golang——延迟调用defer相关推荐

  1. Go基础编程:延迟调用defer

    链客,专为开发者而生,有问必答! 此文章来自区块链技术社区,未经允许拒绝转载. 本篇文章所讲的就是go编程中的延迟调用defer,希望对社区的成员有较多的帮助. 1 defer作用 关键字defer ...

  2. Go 延迟调用 defer 用法详解

    引子 package counterimport ("log""sync" )type Counter struct {mu *sync.MutexValue ...

  3. python延时执行函数_一日一技:在 Python 中实现延迟调用

    一日一技:在 Python 中实现延迟调用 收录于话题 #你不知道的 Python 71个 摄影:产品经理 产品经理的生日餐 熟悉 Golang 的同学都知道,Golang 里面有一个关键词叫做def ...

  4. Golang脱俗的defer

    Golang脱俗的defer 浅谈defer GO中的defer一直都是项目中常用的依赖.无论是解锁,还是关闭文件,或者关闭session,大多都离不开defer.稍微使用过golang的粉(huan ...

  5. 带有Java Util日志记录的Java 8延迟调用

    在博客文章"在Log4j2中更好地执行非日志记录器调用"中 ,我介绍了可以在Log4j 2中使用的方法,这些方法可以减少或避免在基于指定日志级别实际上根本未记录的日志语句中调用方法 ...

  6. js的间隔调用和延迟调用

    计时事件 描述:通过使用js,可以做到在一个设定的时间间隔之后来执行代码,而不是在函数被调用后立即执行,称为计时事件 类型: setInterval--间隔指定的毫秒数不停地执行指定的代码(间隔调用) ...

  7. 记录 activity onStop、onDestroy 延迟调用问题解决过程

    问题背景 在我的项目中,从其它页面回到首页后,其它页面的 onStop.onDestroy 都会延迟调用,大概 7s 左右吧. 思考方向 1.可能是 Home 页面的onStart onResume ...

  8. ios performSelector延迟调用及取消问题

    iOS延迟调用NSObject提供的相关函数如下: /**************** Delayed perform ******************/@interface NSObject ( ...

  9. Unity中在Editor下的延迟调用

    Unity中在Editor下的延迟调用 说到延迟调用, 大家肯定首先想到的是MonoBehavior的协程, 但是在Editor不太好用. 我们这里给出两个方案供大家选择. async 第一种比较简单 ...

最新文章

  1. 人脑为何能够快速学习新知识? 用AI的视角来分析
  2. python基础十四之匿名函数
  3. 事件触发控制_前端性能优化:事件的节流throttle与防抖debounce
  4. 进制转换c语言代码_奇怪的C语言代码,有些函数在变量前加上(void)是什么类型转换?...
  5. 安卓案例:在同一Activity里切换Fragment
  6. Shadow Map阴影贴图技术之探 【转】
  7. Portlet MVC框架
  8. mysql5.5连不上主机_mysql5.5主从同步排错
  9. 设计模式之GOF23桥接模式
  10. Android本地音乐播放器的制作
  11. Eviews10 如何将季度数据转为月度数据(低频转高频)
  12. 从零点一开始机器学习之TF1.0版本HDF5转换为saved_model
  13. 微信 PC(电脑端) 多开批处理
  14. 【荐】女性新手必看的停车入位技巧图解
  15. 微信会员卡,信息类目字段跳转小程序【custom_field1】【巨巨巨巨坑】
  16. 解题笔记(39)——过河问题
  17. HAProxy入门(一)
  18. 我国超级计算机型号,中国成功研制千万亿次超级计算机天河一号
  19. PE中Ghost 使用详解
  20. linux内核时钟工作原理,需要学习并了解Linux时钟的原理及其应用

热门文章

  1. capture 部分元器件编号_十大电子元器件及其相关基础知识
  2. mysql 数据库中数据去重,oracle数据库中如何达到像mysql数据库中group by 那种去重的效果..求大神解答...
  3. php csrf攻击 xss区别,XSS与CSRF攻击及防御方法
  4. mysql 严格模式_MySQL 开启/关闭 严格模式(Strict Mode)
  5. java中main缺少主体_缺少方法主体,或声明了摘要
  6. a jquery 标签点击不跳转_form标签的action属性怎么用?form标签action属性的用法介绍(附实例)...
  7. Java字符编码介绍
  8. 【OpenCV 例程200篇】14. 图像与标量相加(cv2.add)
  9. 新手博客,开博立言_Youcans2021
  10. HTML文本下划线效果,聊聊CSS中文本下划线_CSS, SVG, masking, clip-path, 会员专栏, text-decoration 教程_W3cplus...