Go语言defer详解
1. 使用defer的优势
defer一般用于资源的释放和异常的捕捉, 作为Go语言的特性之一.
defer 语句会将其后面跟随的语句进行延迟处理. 意思就是说 跟在defer后面的语言 将会在程序进行最后的return之后再执行.
在 defer 归属的函数即将返回时,将延迟处理的语句按 defer 的逆序进行执行,也就是说,先被 defer 的语句最后被执行,最后被 defer 的语句,最先被执行。
1.1 资源的释放
一般我们写读取文件的代码如下
func CopyFile(dstName, srcName string) (written int64, err error) {src, err := os.Open(srcName)if err != nil {return}dst, err := os.Create(dstName)if err != nil {return }dst.Close()src.Close()return
}
在程序最开始,os.Open及os.Create打开了两个文件资源描述符,并在最后通过file.Close方法得到释放,在正常情况下,该程序能正常运行,一旦在dstName文件创建过程中出现错误,程序就直接返回,src资源将得不到释放。因此需要在所有错误退出时释放资源,即修改为如下代码才能保证其在异常情况下的正确性。
即在每个err里面如果发生了异常, 要及时关闭src的资源.
这个问题出现在加锁中也非常常见
l.lock()// 如果下面发生了异常
// 我们需要在每个err处理块中都加入l.unlock()来解锁
// 不然资源就得不到释放, 就会产生死锁
if err != nil {l.unlock()return
}
但是这样做未免太麻烦了, defer优雅的帮我们解决了这个问题
比如我们可以这样
src, err := os.Open(srcName)defer src.Close()if err != nil {return}dst, err := os.Create(dstName)defer dst.Close()if err != nil {return }------------------------------------------l.lock()defer l.unlock()......if err != nil {return }......
这样写的话, 就不需要在每个异常处理块中都加上Close() 或者 unlock()语句了
1.2 异常的捕捉
程序在运行时可能在任意的地方发生panic异常,例如算术除0错误、内存无效访问、数组越界等,这些错误会导致程序异常退出。在很多时候,我们希望能够捕获这样的错误,同时希望程序能够继续正常执行。一些语言采用try…catch语法,当try块中发生异常时,可以通过catch块捕获。
Go语言使用了特别的方式处理这一问题。defer的特性是无论后续函数的执行路径如何以及是否发生了panic,在函数结束后一定会得到执行,这为异常捕获提供了很好的时机。异常捕获通常结合recover函数一起使用。
如上所示,在executePanic函数中,手动执行panic函数触发了异常。当异常触发后,函数仍然会调用defer中的函数,然后异常退出。输出如下,表明调用了defer中的函数,并且main函数将不能正常运行,程序异常退出打印出栈追踪信息。
如下所示,当在defer函数中使用recover进行异常捕获后,程序将不会异常退出,并且能够执行正常的函数流程。如下输出表明,尽管有panic,main函数仍然在正常执行后退出。
使用了recover函数后, 程序将不会异常退出, 仍会正常执行
2. 多个defer语句的执行顺序
当有多个 defer 行为被注册时,它们会以逆序执行(类似栈,即后进先出), 相当于开辟了一个延时调用栈
func main() {fmt.Println("defer begin")// 将defer放入延迟调用栈defer fmt.Println(1)defer fmt.Println(2)// 最后一个放入, 位于栈顶, 最先调用defer fmt.Println(3)fmt.Println("defer end")
}
执行的结果就是
// 先打印正常语句
defer begin
defer end
// 然后按从上到下的顺序执行defer调用栈中的语句
3
2
1
Go语言defer详解相关推荐
- Go语言defer详解笔记
Go语言defer详解 1.defer概述: defer是用来声明一个延迟函数,并且将这个函数放到一个栈中,它的调用时间在return执行之前,详细来讲,它的执行时间在return的值赋值之后,在 ...
- python语言编程基础-Python语言入门详解!快速学成Python!
原标题:Python语言入门详解!快速学成Python! 很多技能是被职场所需要的,但很可惜... 这些技能在大学中并学习不到. 大学和职场现实存在的横沟对大部分同学来说难以跨越或碰得头破血流... ...
- python语言入门m-Python语言入门详解!快速学成Python!
今日主题 "Python语言入门详解" 近两年来,Python语言借着数据科学和人工智能的"东风"成为了最流行的编程语言--街头巷尾人们口口相传.同时,Pyth ...
- C语言之详解#ifdef等宏
C语言之详解#ifdef等宏 这几个宏是为了进行条件编译.一般情况下,源程序中所有的行都参加编译.但是有时希望对其中一部分内容只在满足一定条件才进行编译,也就是对一部分内容指定编译的条件,这就是&qu ...
- c语言 宏教程 pdf,C语言之详解_ifdef等宏.pdf
C 语言之详解 #ifdef 等宏 指令用途 #空指令,无任何效果 #include 包含一个源代码文件 #define 定义宏 #undef 取消已定义的宏 #if 如果给定条件为真,则编译下面代码 ...
- 代码检查规则:Python语言案例详解
在之前的文章中代码检查规则:Java语言案例详解学习了Java的检查规则.我们今天将学习<代码检查规则:Python语言案例详解>,内容主要分为两个部分:Python的代码检查规则和Pyt ...
- 代码检查规则:Java语言案例详解
本节课程为<代码检查规则:Java语言案例详解>, 通常情况下Java的代码检查规则可以分为以下十类: 接下来,让我们具体来看看每个分类的内容. 一.源文件规范 该类规范主要从文件名.文件 ...
- Linux_arm_启动_c语言部分详解,[原创]Linux arm 启动 c语言部分详解第四讲
Linux arm启动c语言部分详解第四讲(from setup_per_cpu_areas();) Written by leeming 上面的setup_arch花了我们大量的篇幅,现在我们要继续 ...
- c 语言中 %是什么运算符,C 语言基础----详解C中的运算符
C语言中又有哪些运算符呢? 如下所示: ※ 算术运算符 ※ 赋值运算符 ※ 关系运算符 ※ 逻辑运算符 ※ 三目运算符 C语言基本算术运算符如下表: 除法运算中注意: 如果相除的两个数都是整数的话,则 ...
最新文章
- 趣谈HTTP协议中的那些MIME header
- 【jQuery源码】select方法
- 场景数据的动态更新setDataVariance(osg::Object::DYNAMIC) (转)
- 设计模式Adapter模式的五分钟
- [css] 鼠标事件css的:hover和js的mouseover有什么区别?
- css怎样使弹跳的小球旋转,如何使用纯CSS实现小球跳跃台阶的动画效果(附源码)...
- ios 中文输入法 完成事件_让聊天更方便 百度输入法开启AI助聊功能
- IIS6.0系统日志中出现此错误Timer_MinBytesPerSecond,Timer_ConnectionIdle
- python 表格处理项目该如何分工_python 处理 Excel 表格
- 对话赫拉利与李飞飞:人工智能影响人类的四大问题
- oracle如何导入用户数据文件,oracle的dmp数据文件的导出和导入以及创建用户
- 秋名山老司机从上车到翻车的悲痛经历,带你深刻了解什么是Spark on Hive!
- 有道获取单词读音api
- 腾讯云服务器修改ssh端口,简谈腾讯云更换SSH登录端口
- 基于MATLAB的特殊函数积分
- 相机照片大小设置_我应该为运动照片使用哪些相机设置?
- 咕咚已上传服务器怎到不丁微信,微信运动怎样使用咕咚数据?
- 2021届计算机女硕士秋招面试惨痛经历完结
- ssl证书购买后如何认证签发
- Allegro(17.2)——常用菜单栏(3)
热门文章
- Leetcode 剑指 Offer 42. 连续子数组的最大和 (每日一题 20211014)
- 边界都是1的最大正方形大小
- 机器学习笔记 时间序列预测(最基本的方法【benchmark】)
- pandas 笔记:multi-index
- R语言实战应用精讲50篇(二十九)-R语言算法应用案例:路径路网轨迹绘图分析(英国自行车数据库)
- tableau必知必会之运用本福德定律(Benford‘s law)验证数据真实性
- 增强学习(一) ----- 基本概念
- Python 黑魔法 --- 描述器(descriptor)
- TensorFlow2简单入门-图像加载及预处理
- Spring Boot 2.0官方文档之 Actuator