Go语言defer详解

1.defer概述:

​ defer是用来声明一个延迟函数,并且将这个函数放到一个栈中,它的调用时间在return执行之前,详细来讲,它的执行时间在return的值赋值之后,在返回之前。通常可以用来做一些资源的释放等。


具体规则

1defer的内容虽然会在函数的最后执行,但是defer内的参数会在defer语句声明时就确定。

2)defer之后内容会在defer栈中,先压入栈的最后执行,也就是最先声明的defer函数会最后才执行。

​ 这么设置的原因是defer’被设计用来释放资源,因为资源一般都有依赖性,所以需要先释放最后调用的资源,因此设计为FILO

3)defer可以操作主函数的具名返回值

​ defer的执行时间在函数对return的值赋值之后,

defer的实现底层结构

//defer 的结构和一般的函数类似,包含栈指针,程序计数器,函数地址等
type _defer struct {sp uintptr //函数栈指针pc uintptr //程序计数器fn *funcval //函数地址link *_defer //指向自身结构的指针,用于链接多个defer
}

2.defer的常见用法

1)拦截panic

defer的运行机制决定了无论函数是执行到函数末尾返回还是中途返回又或者是中途遇到了panic,此时已经声明的defer依旧会被调度执行,因此可以拦截painc根据需要对panic进行处理。并且可以尝试从panic中恢复。

遇到panic时,遍历本协程的defer链表,并执行defer。在执行defer过程中:遇到recover则停止panic,返回recover处继续往下执行。如果没有遇到recover,遍历完本协程的defer链表后,向stderr抛出panic信息。

2)修改函数的具名返回值

3)输出调试信息

可以用来输出日志等信息。

4)还原变量旧值

在Go标准库中,syscall包下有使用过,将变量旧值赋给零一变量,使用defer函数还原

3.关于defer的几个关键问题

1.明确哪些函数可以做为defered函数

​ 对于有返回值的自定义函数或者方法,返回值会在defered函数调用时被自动丢弃,对于有返回值的内建函数,直接defer会panic,因此可以使用一个包裹它的匿名函数来满足要求。

defer func () {  //使用 _ 来接收append返回的结果,这时就不会panic_ = append(s1,11)
}()

2.把握defer后表达式的求值时机

​ defer关键字后的表达式是在将deferred函数注册到deferred函数栈的时候进行求值的。即在函数中声明时就已经对表达式求值

3.知晓defer带来的性能损耗

​ 在1.14版本之后,defer的性能损耗变得很低

4.defer三个重要的函数运行结果

defer函数定义时,对外部变量有两种引用方式,分别是作为函数参数和作为闭包引用。作为函数参数,在defer时就会将值传递给defer然后压入defered栈作为闭包引用的话,则会在defer函数真正调用时根据整个上下文来确定当前的值

defer后面的语句在执行的时候,函数调用的参数会被保存起来,也就是复制了一份。真正执行的时候,实际上用到的是这个复制的变量,因此如果此变量是一个“值”,那么就和定义的时候是一致的。如果此变量是一个“引用”,那么就可能和定义的时候不一致。

func d1 (){for i := 3; i > 0 ; i -- {j := i defer func () {fmt.Println(j)}()}
}
//此函数的输出值为1 2 3
func d2 (){for i := 3; i > 0 ; i -- {defer func () {fmt.Println(i)}()}
}
//此函数的输出值为 0 0 0
//因为匿名函数不包含参数,所以这一延迟函数在for循环之后被评估
func d3 (){for i := 3; i > 0 ; i -- {defer func (n int) {fmt.Println(n)}(i)}
}
//此函数的输出值为1 2 3

第三个代码块为最佳解决方案。将变量的值传入匿名函数中

defer包含panic

defer func() {if err := recover(); err != nil{fmt.Println(err)}else {fmt.Println("fatal")}
}()defer func() {panic("defer panic")
}()panic("panic") //代码执行结果为defer panic

panic只有最后一个可以被recover函数捕获,当上述代码触发painc时,会触发defer执行,defer中的panic将会覆盖掉之前的panic被捕获


Go语言defer详解笔记相关推荐

  1. C#语言入门详解笔记(5)—P10、P11、P12 操作符详解_1_2_3

    C#语言入门详解_哔哩哔哩_bilibiliC#语言入门详解搬运,随youtube上进度更新.刘老师的C#视频教程到30集就告一段落了,感谢刘老师在这5年间的付出.能上youtube的同学可以去刘老师 ...

  2. C#语言入门详解笔记(9)—P19 委托详解

    C#语言入门详解_哔哩哔哩_bilibiliC#语言入门详解搬运,随youtube上进度更新.刘老师的C#视频教程到30集就告一段落了,感谢刘老师在这5年间的付出.能上youtube的同学可以去刘老师 ...

  3. Go语言defer详解

    1. 使用defer的优势 defer一般用于资源的释放和异常的捕捉, 作为Go语言的特性之一. defer 语句会将其后面跟随的语句进行延迟处理. 意思就是说 跟在defer后面的语言 将会在程序进 ...

  4. python语言编程基础-Python语言入门详解!快速学成Python!

    原标题:Python语言入门详解!快速学成Python! 很多技能是被职场所需要的,但很可惜... 这些技能在大学中并学习不到. 大学和职场现实存在的横沟对大部分同学来说难以跨越或碰得头破血流... ...

  5. python语言入门m-Python语言入门详解!快速学成Python!

    今日主题 "Python语言入门详解" 近两年来,Python语言借着数据科学和人工智能的"东风"成为了最流行的编程语言--街头巷尾人们口口相传.同时,Pyth ...

  6. C语言之详解#ifdef等宏

    C语言之详解#ifdef等宏 这几个宏是为了进行条件编译.一般情况下,源程序中所有的行都参加编译.但是有时希望对其中一部分内容只在满足一定条件才进行编译,也就是对一部分内容指定编译的条件,这就是&qu ...

  7. c语言 宏教程 pdf,C语言之详解_ifdef等宏.pdf

    C 语言之详解 #ifdef 等宏 指令用途 #空指令,无任何效果 #include 包含一个源代码文件 #define 定义宏 #undef 取消已定义的宏 #if 如果给定条件为真,则编译下面代码 ...

  8. 代码检查规则:Python语言案例详解

    在之前的文章中代码检查规则:Java语言案例详解学习了Java的检查规则.我们今天将学习<代码检查规则:Python语言案例详解>,内容主要分为两个部分:Python的代码检查规则和Pyt ...

  9. 代码检查规则:Java语言案例详解

    本节课程为<代码检查规则:Java语言案例详解>, 通常情况下Java的代码检查规则可以分为以下十类: 接下来,让我们具体来看看每个分类的内容. 一.源文件规范 该类规范主要从文件名.文件 ...

最新文章

  1. Bzoj4212--神牛养成计划
  2. java request payload_java 模拟 post request payload
  3. 数据查询和业务流分开_数据仓库介绍与实时数仓案例--阿里
  4. 每天一道Leetcod或者Codeforce算法系列
  5. Exchange Server2010系列之十一:部署CAS+HT角色高可用性
  6. 1756冗余_AB冗余模块1756-RM
  7. JKD源码系列(4)-AbstractStringBuilder
  8. python 实现字典树_python字典树(Trie)的实现
  9. 树莓派蜜罐节点部署实战
  10. java 流已被关闭_mybatis oracle java.sql.SQLException: 流已被关闭问题
  11. CSS语法规范(CSS、HTML)
  12. 顺情说好话,耿直讨人嫌
  13. 一起瞅一下那些经典案例是如何产业落地的~
  14. 如何在NEO区块链上实现信息加密
  15. CSS实现文字竖排效果
  16. Vbs判断两个Excel文件的内容--将两个Excel文件相同内容写入新建的Excel文件内
  17. win10亮度怎么调_装好原版win10后,没有这样设置过,你的系统怎么可能好用!...
  18. XRD格式转换 神器
  19. 定时器0练习,利用左循环函数_crol_(a,b)
  20. win10解决cmd无法切换盘符的问题

热门文章

  1. c语言strcmp函数用法_strcmp()C库函数用法和示例
  2. 九景衢铁路上的“夜精灵”
  3. WordPress果果加速插件使用教程
  4. 从零开始搭建基于Xcode7的IOS开发环境和免开发者帐号真机调试运行第一个IOS程序HelloWorld
  5. 字符串的常用拼接方法
  6. js删除数组里的某个元素
  7. 我们都在不断赶路忘记了出路
  8. 开始SpringCloud
  9. 【GB】国标查询网站
  10. 西门子S7-300如何接入组态王