golang defer 详解

defer 的作用和执行时机

go 的 defer 是用来延迟执行函数的,而且延迟发生在调用函数 return 之后,比如:

func a() int {defer b()return 0
}

b 的执行是发生在 return 0 之后,注意 defer 的语法,关键字 defer 之后是函数的调用。

defer 的重要用途一:清理释放资源

由于 defer 的延迟特性,defer 常用在函数调用结束之后清理相关的资源,比如:

f, _ := os.Open(filename)
defer f.close()

文件资源的释放会在函数调用结束之后借助 defer 自动运行,不需要时刻记住哪里的资源需要释放,打开和释放必须相对应。

用一个例子深刻诠释一下 defer 带来的便利和简洁。

代码的主要目的是打开一个文件夹,然后复制内容到另一个新的文件中,没有 defer 时这样写:

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 { // 1return}written, err = io.Copy(dst, src)dst.Close()src.Close()return
}

代码在 #1 处返回之后,src 文件没有执行关闭操作,可能会导致资源不能正确释放,改用 defer 实现:

func CopyFile(dstName, srcName string) (written int64, err error) {src, err := os.Open(srcName)if err != nil {return}defer src.Close()dst, err := os.Create(dstName)if err != nil {return}defer dst.Close()return io.Copy(dst, src)
}

这样一来,src 和 dst 都能及时清理和释放,无论 return 在什么地方执行。

鉴于 defer 的这种作用,defer 常用来释放数据库连接,文件打开句柄等释放资源的操作。

defer 的重要用途二:执行 recover

defer 的函数在 return 之后执行,这个时机点正好可以捕获函数抛出的 panic,因而 defer 的另一个重要用途就是执行 recover

recover 只有在 defer 中使用才更有意义,如果在其他地方是使用,由于 program 已经调用结束而提前返回而无法有效捕捉错误。

package mainimport ("fmt"
)func main() {defer func() {if ok := recover(); ok != nil {fmt.Println("recover")}}()panic("error")
}

记住 defer 要放在 panic 执行之前。

多个 defer 的执行顺序

defer 的作用就是把关键字之后的函数执行压入一个栈中延迟执行,多个 defer 的执行顺序是后进先出 LIFO:

defer func() { fmt.Println("1") }()
defer func() { fmt.Println("2") }()
defer func() { fmt.Println("3") }()

输出顺序是 321。

这个特性可以对一个 array 实现逆序操作。

被 deferred 函数的参数在 defer 时确定

这是 defer 的特点,一个函数被 defer 时,它的参数在 defer 时进行计算确定,即使 defer 之后参数发生修改,对已经 defer 的函数没有影响。什么意思?看例子:

func a() {i := 0defer fmt.Println(i)i++return
}

a 执行输出的是 0 而不是 1,因为 defer 时,i 的值是 0,此时被 defer 的函数参数已经进行执行计算并确定了。

再看一个例子:

package mainimport ("fmt"
)func calc(index string, a, b int) int {ret := a + bfmt.Println(index, a, b, ret)return ret
}
func main() {a := 1b := 2defer calc("1", a, calc("10", a, b))a = 0return
}

执行代码输出:

10 1 2 3 
1 1 3 4

defer 函数的参数,第三个参数在 defer 时就已经计算完成并确定,第二个参数 a 也是如此,无论之后 a 变量是否修改都不影响。

被 defer 的函数可以读取和修改带名称的返回值

package mainimport "fmt"func main() {fmt.Println(c())
}func c() (i int) {defer func() { i++ }()return 1
}

defer 的函数是在 return 之后执行的,可以修改带名称的返回值,上面的函数 c 返回的是 2

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/629115.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

安全狗方案入选工信部《2023年工业和信息化领域数据安全典型案例名单》

近日,工业和信息化部网络安全管理局公布了2023年工业和信息化领域数据安全典型案例名单。 安全狗与厦门卫星定位应用股份有限公司、中移 (上海) 信息通信科技有限公司联合申报的智慧交通云数据安全与隐私保障典型案例也成功入选。 厦门服云信息科技有限公司&#…

Vue-24、Vue过滤器

1、效果 2、过滤器实现 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>过滤器</title><script type"text/javascript" src"https://cdn.jsdelivr.net/npm/vue2/dist/vue.…

mac 系统中vscode 返回上一次文件编辑位置快捷键

mac 系统中vscode 返回上一次文件编辑位置快捷键 以下内容由chatgpt中文网 动态生成,助力开发找我 方式1&#xff1a; Command -&#xff1a;返回到上一个编辑位置。 方式2 control -&#xff1a;返回到上一个编辑位置。

OpenCV-Python(45):立体图像中的深度地图

基础 在OpenCV中&#xff0c;深度地图通常是通过计算立体视觉&#xff08;stereo vision&#xff09;或结构光&#xff08;structured light&#xff09;技术得到的。立体视觉是通过将两个或多个摄像机&#xff08;或图像&#xff09;的视角结合起来&#xff0c;计算物体的深度…

Kafka 的架构

实验过程 1.三个虚拟机中解压kafka软件包 tar -zxvf kafka_2.11-1.1.1.tgz 2.修改 3 个节点配置文件 在 zookeeper 节点&#xff0c;进入 kafka_2.11-1.1.1/config 目录下&#xff0c;编辑 server.properties 文件 [rootdb1 ~]# cd kafka_2.11-1.1.1/config [rootdb1 con…

智能路由器 端口映射 (UPnP) Padavan内网端口映射配置方法

新版本Padavan 4.4内核的端口映射配置和老版本的不太一样,因为新版本默认是启用的 UPnP端口映射, 同时默认使用的是 IGD UPnP自动端口映射, UPnP名词解释: UPnP通用即插即用&#xff0c;是一组协议的统称&#xff0c;是一种基于TCP/IP、UDP和HTTP的分布式、开放体系&#xff…

P9847 [ICPC2021 Nanjing R] Crystalfly 题解 (SPJ)

[ICPC2021 Nanjing R] Crystalfly 传送门&#xff1f; 题面翻译 给定一个 n ( 1 ≤ n ≤ 1 0 5 ) n(1\le n\le10^5) n(1≤n≤105) 个节点的树&#xff0c;每个节点上有 a i a_i ai​ 只晶蝶。派蒙最初在 1 1 1 号节点&#xff0c;并获得 1 1 1 号节点的所有晶蝶&#xf…

Java设计模式之策略模式详解

Java设计模式之策略模式详解 大家好&#xff0c;我是免费搭建查券返利机器人赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天&#xff0c;让我们一同踏入Java设计模式之策略模式的世界&#xff0c;探讨代码中的…

NetSuite学习笔记 - 中心

一、什么是中心&#xff1f; 对于每个用户&#xff0c;NetSuite 会根据用户的指定角色显示一组可变的标签页面&#xff0c;称为中心。通俗来讲呢&#xff0c;NetSuite的中心其实就是我们常说的“导航菜单”。 只是在我过去常见的系统中&#xff0c;导航菜单一般都是固定的&am…

Elasticsearch Windows部署-ELK技术栈

1、下载Elasticsearch、kibana、logstash 本文不介绍ELK相关原理知识&#xff0c;只记录部署操作过程 下载地址Past Releases of Elastic Stack Software | Elastic 选择同一版本&#xff0c;这里选择是当前最新版本8.11.3 解压放在同目录下&#xff0c;方便后续操作与使用 …

python 创建虚拟环境

为啥需要创建虚拟环境 在ubuntu直接pip安装的错误&#xff0c;规避自己安装的包与系统使用包之间的冲突 ➜ ~ pip3 install fastapi error: externally-managed-environment This environment is externally managed ╰─> To install Python packages system-wide, try a…

GPT实战系列-实战Qwen在Cuda 12+24G部署方案

GPT实战系列-实战Qwen在Cuda1224G部署方案 ChatGLM4进行新闻发布&#xff0c;但还没有开源更新&#xff0c;在此之际&#xff0c;实战部署测试Qwen大模型。目前Qwen的口碑貌似还不错&#xff0c;测试显卡内存24G&#xff0c;毕竟有限&#xff0c;排除了Qwen14非量化方案Qwen-1…

浅入浅出Spring架构设计

浅入浅出Spring架构设计 前言 为什么需要Spring? 什么是Spring? 对于这样的问题&#xff0c;大部分人都是处于一种朦朦胧胧的状态&#xff0c;说的出来&#xff0c;但又不是完全说的出来&#xff0c;今天我们就以架构设计的角度尝试解开Spring的神秘面纱。 本篇文章以由浅…

RK3566 linux加入uvc app

SDK中external/uvc_app/目录提供了将板卡模拟成uvc camera的功能。 一、buildroot使能uvc_app 1、进入到buildroot目录 在sdk目录下执行以下命令&#xff1a; cd buildroot 2、选择defconfig 执行命令&#xff1a; source build/envsetup.sh 输入数字然后回车选择板卡&…

【Vue3】3-4 : 组件的属性与事件是如何进行处理的

有时候组件上的属性或事件并不想进行组件通信&#xff0c;那么Vue是如何处理的呢&#xff1f; 组件的属性与事件 默认不通过props接收的话&#xff0c;属性会直接挂载到组件容器上&#xff0c;事件也是如此&#xff0c;会直接挂载到组件容器上。可通过 inheritAttrs 选项阻止…

Java中Redis常用的20个方法

开头语&#xff1a; 大家好&#xff01;欢迎来到本篇博客&#xff0c;今天我们将探讨Java中Redis的常用方法。作为一种强大的缓存和数据存储工具&#xff0c;Redis在Java应用中扮演着重要的角色。我们将介绍20个常用的Redis方法&#xff0c;希望对大家在Java开发中更好地使用R…

两数之和(Hash表)[简单]

优质博文&#xff1a;IT-BLOG-CN 一、题目 给定一个整数数组nums和一个整数目标值target&#xff0c;请你在该数组中找出"和"为目标值target的那两个整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元…

HC小区管理系统商用测试用例

HC小区管理系统商用测试用例 说明 HC小区管理系统商用之前&#xff0c;必须要经过严格的测试&#xff0c;可能因为环境差异&#xff0c;以及配置差异等导致生产环境不稳定&#xff0c;或者存在系统bug。 1.1、操作视频 hc_java110的个人空间-hc_java110个人主页-哔哩哔哩视…

Spark—shell,Hbase—shell

Spark&#xff1a; SPARK SQL results spark.sql( "SELECT * FROM people") //读取JSON文件 val userScoreDF spark.read.json("hdfs://master:9000/people.json") Spark内置函数的使用 除select()外&#xff0c;还可以使用filter()、groupBy()等方…

工具推荐 |Devv.ai — 最懂程序员的新一代 AI 搜索引擎

介绍 伴随 GPT 的出现&#xff0c;我们可以看到越来越多的 AI 产品&#xff0c;其中也不乏针对程序员做的代码生成工具。 今天介绍的这款产品是一款针对中文开发者的 AI 搜索引擎&#xff0c;Devv.ai 使用 Devv.ai 的使用非常简单&#xff0c;就是传统的搜索场景&#xff…