defer特性:

  1. 关键字 defer 用于注册延迟调用。
  2. 这些调用直到 return 前才被执。因此,可以用来做资源清理。
  3. 多个defer语句,按先进后出的方式执行。
  4. defer语句中的变量,在defer声明时就决定了。

defer用途:

  1. 关闭文件句柄
  2. 锁资源释放
  3. 数据库连接释放
package mainimport "fmt"func main() {var users [5]struct{}for i := range users {defer fmt.Println(i)}
}

输出:4 3 2 1 0 ,defer 是先进后出

package defer_testimport ("fmt""testing"
)func TestDefer1(t * testing.T) {var users [5]struct{}for i := range users {defer func() { fmt.Println(i) }()}
}

输出结果: 4 4 4 4 4
是否在想一个问题,输出结果不是 4 3 2 1 0 , 由于是闭包用到的变量 i 在执行的时候已经变成了4 , 所以输出全部是 4, 如何正常输出。4 3 2 1 0 ? 不用闭包,换成函数即可。

func TestDefer2(t *testing.T) {var users [5]struct{}for i := range users {defer Print(i)}
}func Print(i int) {fmt.Println(i)
}

函数的输出结果是 : 4 3 2 1 0

再看个结构体的例子

func (t *Users) GetName(){fmt.Println(t.name)
}func TestDefer3(t * testing.T){list := []Users{{"乔峰"}, {"慕容复"},{"欧阳克"}}for _, t := range list {defer t.GetName()}
}

发现没,输出的结果竟然是 欧阳克 欧阳克 欧阳克

不是欧阳克 慕容复 乔峰

如何要输出 : 欧阳克 慕容复 乔峰

写个函数:

type Users struct {name string
}func (t *Users) GetName(){fmt.Println(t.name)
}func GetName(t Users){t.GetName()
}func TestDefer4(t *testing.T) {list := []Users{{"乔峰"}, {"慕容复"},{"欧阳克"}}for _, t := range list {defer GetName(t)}
}

函数输出结果:
欧阳克
慕容复
乔峰

如果不想多写一个函数,输出
欧阳克
慕容复
乔峰

要怎么搞?复制一份即可

type Users struct {name string
}func (t *Users) GetName() {fmt.Println(t.name)
}func TestDefer5(t *testing.T) {list := []Users{{"乔峰"}, {"慕容复"}, {"欧阳克"}}for _, t := range list {t1 := tdefer t1.GetName()}
}

输出结果:
欧阳克
慕容复
乔峰

defer 后面的语句在执行的时候,函数调用的参数会保存起来,复制一份,但是不执行。

多个 defer 注册,采用的是 FILO 先进后出的方式,哪怕函数发生错误, 这些调用依然会被执行。

func users(i int) {defer println("北丐")defer println("南帝")defer func() {println("西毒")println(10 / i) // 异常未被捕获,逐步往外传递,最终终止进程。}()defer println("东邪")
}
func TestDefer6(t *testing.T) {users(0)println("武林高手排行榜,这里不会被输出")
}

defer 与 return

在有命名返回值的函数中, 执行 return "风清扬"的时候实际上已经将 s 的值重新赋值为 风清扬

func Users2() (s string) {s = "乔峰"defer func() {fmt.Println("延迟执行后:" + s)}()return "清风扬"
}func TestDefer7(t *testing.T) {Users2() // 输出:延迟执行后:清风扬
}

输出结果:

延迟执行后:清风扬
--- PASS: TestDefer7 (0.00s)
PASS

欢迎关注公众号:程序员开发者社区

参考资料
  • https://www.cnblogs.com/phpper/p/11984161.html
  • https://draveness.me/golang/docs/part2-foundation/ch05-keyword/golang-defer/

Go defer 使用相关推荐

  1. Go 学习笔记(17)— 函数(03)[defer 定义、defer 特点、defer 释放资源]

    1. defer 定义 Go 函数的关键字 defer 可以提供注册多个延迟调用,只能出现在函数内部,在 defer 归属的函数即将返回时,将延迟处理的语句按 defer 的逆序进行执行,这些调用遵循 ...

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

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

  3. js的defer属性

    js的defer属性说明:<script src="js.js" type="text/javascript defer="defer"/> ...

  4. golang源码分析:defer流程分析

    defer defer是golang中使用的延迟调用的函数,该函数的使用场景就是如果函数执行出错(panic),也能够通过recover方式进行捕捉错误并将出错时的一些资源进行回收,如果在性能有要求的 ...

  5. Script标签的async和defer

    之前有写过HTML页面渲染过程,知道了JavaScript是会阻塞DOM解析的,所以我们会把script标签放到底部防止阻塞HTML解析.其实script还有两个属性,async和defer,也是可以 ...

  6. prefetch 和preload_前端preload, prefetch,dns-prefetch,defer,async了解一下

    preload 通过rel="preload"进行内容预加载 元素的 rel 属性的属性值preload能够让你在你的HTML页面中 元素内部书写一些声明式的资源获取请求,可以指明 ...

  7. GO语言教程4:defer(延迟语句)详解

    文章目录 1.defer语句格式 2.defer执行的时间 3.defer语句的作用 4.defer语句执行的顺序 5.defer与return的value之间的关系 6.用defer进行代码跟踪 7 ...

  8. script标签的defer属性

    defer 属性规定是否对脚本执行进行延迟,直到页面加载为止. 有的 javascript 脚本 document.write 方法来创建当前的文档内容,其他脚本就不一定是了. 如果您的脚本不会改变文 ...

  9. Go笔记-错误处理和defer

    为什么80%的码农都做不了架构师?>>> error error类型的声明可在builtin包中查看: type error interface {Error() string } ...

  10. Js高设笔记1-2章 defer and async

    1,js是由ECMAscript ,dom ,bom组成的专为网页交互而设计的脚本语言.js是脚本语言之一. 2,MIME,是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的 ...

最新文章

  1. Postman批量跑接口
  2. VTK:PolyData之PolyDataToUnstructuredGrid
  3. label 标签里面元素点击事件
  4. Qt学习笔记-编写简易的音乐播放器
  5. vSphere 7 With K8s系列07:客户端工具使用
  6. 毕设周记——确定选题
  7. win10安装nessus8.10
  8. node 简繁体转换_简体繁体转换
  9. IB选课指南及热门专业选课建议
  10. android 点击提示音,Android 下实现------蜂鸣提示音和震动
  11. 共阳极管的代码_共阳极数码管显示数字程序的进化
  12. ps有一款比较好用的插件也就是调色插件用过吗
  13. R 语言中添加辅助线(ggplot2)
  14. Paxos太难懂?五张图读懂Paxos协议
  15. 第十三届蓝桥杯国赛真题 PythonB组 复盘以及获奖感言(国一!!!)
  16. c语言中输入scanf与getchar的啃爹之处
  17. 第一次参加区赛的收获——By Yvonne
  18. 判断OOBE 完成状态
  19. delphi function 与 procedure
  20. 每天学一点Scala之implict 隐式参数

热门文章

  1. 人总是这样,对亲近的人表现的不好,可是对待陌生人却太宽容
  2. [字典树+KM]hdoj 2813:One fihgt one
  3. eclipse设置背景色为绿色
  4. 技术动态 | AIGC时代知识图谱技术的发展与最佳实践
  5. Vulnhub---potato
  6. 三不朽标准:立德、立功、立言——王阳明和曾国藩谁更完美?
  7. Toolbar使用方法
  8. Python调用FFmpeg库——PyAV
  9. 新能源电动汽车一键启动手机操控智能钥匙
  10. 牛客多校第九场 H Cutting Bamboos —— 主席树