『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,在原文的基础上进行了适当的总结与改编,以适应于国内开发者的理解与使用,水平有限,如果写的不对的地方欢迎大家评论指出 ...
随机推荐
- es6快速入门 系列 - async
其他章节请看: es6 快速入门 系列 async 前文我们已经知道 promise 是一种异步编程的选择.而 async 是一种用于执行异步任务更简单的语法. Tip:建议学完 Promise 在看 ...
- 如何在国产龙芯架构平台上运行c/c++、java、nodejs等编程语言
高能预警:本文内容过于硬核,涉及编译器原理.cpu指令集.机器码.编程语言原理.跨平台原理等计算机专业基础知识,建议具有c.c++.java.nodejs等多种编程语言开发能力,且实战经验丰富的资深开 ...
- kubernetes关闭基于角色的访问控制-匿名访问
1.关闭基于角色的访问控制 如果正在使用一个带有RBAC机制的Kubernetes集群,服务账户可能不会被授权访问API服务器(或只有部分授权).目前最简单的方式就是运行下面的命令查询API服务器,从 ...
- 第14章:部署Java网站项目案例
1 说明 (1) 项目迁移到k8s平台的流程 1) 制作镜像 dockerfile.docker+jenkins持续集成.镜像分类:基础镜像.中间镜像.项目镜像 2) 控制器管理pod 控制器管理po ...
- keycloak~管理平台的查询bug与自定rest中文检索
对于keycloak来说,它的管理平台在它的源码中的admin-client中,它会定义相关的rest接口规范:在我们使用keycloak管理平台时,其中有一个组的查询,在我们查询中文组时,它是不支持 ...
- Mysql 主键的操作
主键:primary key ,主要的键.一张表只能有一个字段可以使用对应的键,用来唯一的约束字段里面的数据,数据不能重复,这种键称之为主键,一张表只能最多有一个主键. 一.增加主键 方法一:在 ...
- AcWing 828. 模拟栈
实现一个栈,栈初始为空,支持四种操作: (1) "push x" – 向栈顶插入一个数x: (2) "pop" – 从栈顶弹出一个数: (3) "em ...
- Spring缓存的注解关键词解释
Spring缓存的注解关键词解释 @Cacheable支持缓存 @Cacheable可以标记在一个方法上,也可以标记在一个类上. 1.当标记在一个方法上时表示该方法是支持缓存的,当标记在一个类上时则表 ...
- 不安装任何软件或脚本使用powershell快速计算文件的MD5/SHA1/SHA256等校验值
有的时候在检查升级过程中需要对xml文件进行签名,而xml文件中一般都需要包含安装包的SHA256值,这里分享一个使用PowerShell快速计算SHA256等其他值的方法. 一.在需要计算文件SHA ...
- python使用笔记002
一.字符串常用方法 1 s = ' ha.hahaha.' 2 print(s.count('a'))#找某一个元素在字符串里出现的次数 3 print(s.index('a'))#找某一个元素的下标 ...