『go成长之路』 defer 作用、典型用法以及多个defer调用顺序,附加defer避坑点,拿来吧你
预习内容
- defer 的作用有哪些?
- 多个 defer 的执行顺序是怎样的?
- defer,return,函数返回值 三者之间的执行顺序
defer的作用
go中的defer是延迟函数,一般是用于释放资源或者收尾工作。
由于defer是具有延迟特性且执行动作是在函数return之后,因此作为资源释放作用再好不过。
- 典型例子:释放锁、关闭文件、关闭链接等
// 释放锁
func getValue() {
s.Lock()
defer s.Unlock()
...
}
// 关闭文件
func read() {
f, err := os.OpenFile("filename", os.O_RDWR, os.ModePerm)
defer f.Close()
...
}
// 关闭链接
func connect() {
resp, err := grequests.Get(s.cfg.GateApiCrossMarginUrl, nil)
defer resp.Close()
...
}
// 收尾工作,defer 同时也是函数,可以做很多收尾相关工作
func closeConnection() {
...
defer func() {
file.close()
close(readChan)
}
...
}
- 还有作用就是捕获 panic,这个功能在defer里也是典型用法
func sendChan() {
// 此处捕获 panic 进行 recover 防止程序崩溃
defer func() {
if ok := recover(); ok != nil {
fmt.Println("recover")
}
}()
// 向已经关闭的chan发送数据,此处会引起 panic
dataChan <- "message"
...
}
defer 释放资源『避坑指南』
资源释放动作一定紧跟资源使用(打开、连接)语句,不然defer可能不会被执行到,导致内存泄露
// 关闭文件
func read() error {
f1, err := os.OpenFile("filename", os.O_RDWR, os.ModePerm)
if err != nil {
return err
}
// 此时,defer还没执行到,提前return了,无效defer导致内存泄露
defer f1.Close()
// 正确用法,紧跟资源使用语句
f2, err := os.OpenFile("filename", os.O_RDWR, os.ModePerm)
defer f2.Close()
if err != nil {
return err
}
}
defer 的调用顺序
墙裂建议不要先看后面的介绍做下面的题目,此处先跳过介绍defer调用顺序,看看下面比较典型的对defer顺序判断,你能看出来几个?
func deferFunc1(i int) (t int) {
t = i
defer func() {
t += 1
}()
return t
}
func deferFunc2(i int) int {
t := i
defer func() {
t += 1
}()
return t
}
func deferFunc3(i int) (t int) {
defer func() {
t += i
}()
return 1
}
func deferFunc4() (t int) {
defer func(i int) {
fmt.Println(i)
fmt.Println(t)
}(t)
t = 0
return 1
}
func ExecDeferFunc() {
// 猜猜下面输出的内容和顺序
fmt.Println(deferFunc1(1))
fmt.Println(deferFunc2(1))
fmt.Println(deferFunc3(1))
deferFunc4()
}
猜想结果可能是:2,2,1,0,0 或者 2,2,1,1,1 ?
估计比较模糊的地方应该是函数返回值 和 return value(函数返回值)关系不明确,还有就是对defer产生作用的时机不明确
正文开始!
再次强调defer是延迟函数,执行动作在return之后,defer相当于是将执行动作压入栈中,越是后面的defer越是先执行,执行顺序是LIFO(后进先出)。
特别指出:有函数返回值的则return将结果写入返回值,defer进行收尾,可以看做 return最先执行,然后return将结果存入返回值,最后defer执行
那么基于刚刚的介绍再回头去看得到的『实际结果是:2,1,2,0,1』
复习内容
- defer 用于资源释放和收尾工作
- 多个 defer 调用顺序是 LIFO(后入先出),defer后的操作可以理解为压入栈中
- defer,return,return value(函数返回值) 执行顺序:首先return,其次return value,最后defer。defer可以修改函数最终返回值。
『go成长之路』 defer 作用、典型用法以及多个defer调用顺序,附加defer避坑点,拿来吧你的更多相关文章
- 『NiFi 学习之路』简介
『NiFi 学习之路』简介 『NiFi 学习之路』入门 -- 下载.安装与简单使用 『NiFi 学习之路』资源 -- 资料汇总 『NiFi 学习之路』把握 -- 架构及主要组件 『NiFi 学习之路』 ...
- 『NiFi 学习之路』自定义 —— 组件的自定义及使用
一.概述 许多业务仅仅使用官方提供的组件不能够满足性能上的需求,往往要通过高度可定制的组件来完成特定的业务需求. 而 NiFi 提供了自定义组件的这种方式. 二.自定义 Processor 占坑待续 ...
- 『NiFi 学习之路』使用 —— 主要组件的使用
一.概述 大部分 NiFi 使用者都是通过 NiFi 的 Processor 来实现自己的业务的.因此,我也主要就 NiFi 官方提供的 Porcessor 进行介绍. 二.Processor 如果你 ...
- 『NiFi 学习之路』把握 —— 架构及主要部件
一.概述 通过前面几篇文章的学习,相信你对 NiFi 有了一个基础性的了解. 数据处理和分发系统 是什么概念? NiFi 系统中数据的传递方式是怎样的? NiFi 的重要 Processor 有哪些? ...
- 『NiFi 学习之路』资源 —— 资料汇总
一.概述 由于 NiFi 是一个比较新的开源项目,国内的相关资料少之又少. 加之,大家都知道,国内的那么些个教程,原创都只是停留在初级使用阶段,没有更多深入的介绍. 再者,其余的文章不是东抄抄就是西抄 ...
- 『NiFi 学习之路』入门 —— 下载、安装与简单使用
一.概述 "光说不练假把式." 官网上的介绍多少让人迷迷糊糊的,各种高大上的词语仿佛让 NiFi 离我们越来越远. 实践是最好的老师.那就让我们试用一下 NiFi 吧! 二.安装 ...
- 『王霸之路』从0.1到2.0一文看尽TensorFlow奋斗史
0 序篇 2015年11月,Google正式发布了Tensorflow的白皮书并开源TensorFlow 0.1 版本. 2017年02月,Tensorflow正式发布了1.0.0版本,同时也标志 ...
- Android成长之路-LayoutInflater和inflate的用法
在这里用Tabhost的例子来说明: package cn.csdn.activity; import android.app.TabActivity; import android.os.Bundl ...
- 『TensorFlow2.0正式版』TF2.0+Keras速成教程·零:开篇简介与环境准备
此篇教程参考自TensorFlow 2.0 + Keras Crash Course,在原文的基础上进行了适当的总结与改编,以适应于国内开发者的理解与使用,水平有限,如果写的不对的地方欢迎大家评论指出 ...
随机推荐
- 8、基本数据类型(dict)
8.1.字典: 1.字典元素用大括号括起来,用逗号分割每个元素,字典元素是"key:value"的形式 dic = { "k1": 'v1', #键值对 &qu ...
- flex发生错误积累。每次遇到错误记录一点点
error #2044: 未处理的 ioerrorevent: text=error #2036: 加载未完成 出现这个问题,因为我是要实现图片编辑裁剪,然后上传.没有上传成功,出现上面的这个错误, ...
- Hadoop:Hadoop的安装
CentOS7安装Hadoop需要有JDK,所以先下载安装JDK后,在进行安装Hadoop 下载Hadoop #联网状态下使用wget命令 wget http://archive.apache.org ...
- C语言:float类型%d输出
float类型%d输出 float a=7.5f; 如果用printf("%d",a);输出的是0. 但float型用%d输出是否一定是0呢,答案肯定不都是0: 为什么 7.5 用 ...
- 电脑通过WIFI连接手机ADB
1.搜索adb wifi 2.安装并开启:根据提示 3.电脑:adb connect 192.168.1.134 a安装ADB TOOLS b安装ADB DRIVER c将ADB TOOLS复制到c: ...
- 用 SwiftUI 五天组装一个微信
GitHub 链接:SwiftUI-WeChatDemo 效果图 实装内容 4 个 Tab 页面 + 聊天界面,使用纯 SwiftUI 搭建而成 应用启动界面 Launch Screen 国际化及应用 ...
- [刘阳Java]_ResourceBundleViewResolver视图解析器_第7讲
ResourceBundleViewResolver是根据proterties文件来找对应的视图来解析"逻辑视图".该properties文件默认是放在classpath路径下的v ...
- DRF使用JWT进行用户认证
1. 首先需要安装第三方依赖包 pip install djangorestframework-jwt 2. 在Django的settings文件中 配置全局的JWT认证类 REST_FRAMEWOR ...
- ODOO14笔记---系统升级崩溃后进不去系统解决办法
一.通过pycharm升级模块: 2.对于已安装odoo模块,升级报错系统崩溃的解决办法:---执行以下SQL update ir_module_module set state ='ins ...
- C++第四十四篇 -- MFC使用ChartCtrl绘制动态曲线
前言 目的:使用控制台程序带MFC类库画一个动态曲线图 参考链接: https://blog.csdn.net/sinat_29890433/article/details/105360032 htt ...