Go中 defer的使用

2023-11-11

简介

defer 是 Golang 中的一个非常有用的关键字,它用于注册延迟调用,也就是一个函数的执行被延迟到调用它的函数返回之后,常用于资源清理、异常处理等场景。

示例

defer 是注册演示执行, 只有再函数返回或者发生panic的时候才会执行, 同时 同一个函数内的多个 defer 注册的调用也遵循先进后出的栈调用原则.
下面是一个用于理解的示例:

package main

import (
	"fmt"
)
func main() {
	defer func() {
		fmt.Println("第一个defer")
	}()
	defer func() {
		fmt.Println("第二个defer")
	}()
	fmt.Println("主程序执行完毕")
	// panic("发生panic了")
	return
}

如上所示, 我们按照顺序使用了两个 defer, 执行结果如下:
在这里插入图片描述
表示两个 defer 都是再return 之后执行的, 而且遵守先进后出的原则.

使用场景

defer 主要用于函数结束前的清理工作,例如在打开文件后 defer 关闭文件,或者在打开数据库后 defer 关闭数据库连接, 还有处理捕获异常.

捕获异常

Go 中,异常处理使用了 panic-recover,当执行较长的代码块时,可能会因为一些不可预见的原因导致程序出现异常,此时可以使用 defer 语句在 panic 发生时自动执行一些清理工作并进行异常处理。例如:

package main

import (
	"fmt"
)

func main() {
	defer func() {
		if err := recover(); err != nil {
      		fmt.Println("defer-recover 开始处理 panic, 不要慌")
			fmt.Println(err)
		}
	}()
	fmt.Println("开始干活了")
	panic("发生panic了")
}

上述代码中,在 main 执行过程中如果出现了 panic,会在 defer 中注册的函数执行后进行异常恢复, 同时打印出对应的信息
执行结果如下:
在这里插入图片描述
发现, panic发生之后, 执行了 defer 的代码, 还获取到了 panic的信息

文件操作

package main

import (
	"fmt"
	"os"
)

func main() {
	f, err := os.OpenFile("text.txt", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0755)
	if err != nil {
		fmt.Println(err)
	}
	defer f.Close()
	n, err := f.WriteString("大家号, 这是一个文件\t")
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(n)
}

上面的代码中, 我们使用 defer 延迟调用释放资源,防止忘记释放资源(关闭文件或解锁), 这样就可以在函数结束的时候自动关闭文件了

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Go中 defer的使用 的相关文章

  • 为什么我不能将左大括号放在下一行?

    当我尝试编译以下代码时遇到奇怪的错误 package main import fmt fmt func main var arr 3 int for i 0 i lt 3 i fmt Printf d arr i 错误如下 unexpect
  • go中有memset的类似物吗?

    在 C 中 我可以使用某些值初始化数组memset https msdn microsoft com en us library aa246471 28v vs 60 29 aspx const int MAX 1000000 int is
  • 复杂数据类型作为 Go 中映射的键

    我正在尝试在 Go 中创建一个由大整数作为键的映射 effective Go 明确指出 结构体 数组和切片不能用作映射键 因为这些类型上没有定义相等性 这是有道理的 我当然可以将大整数转换为字符串并使用字符串作为键 但我在这里寻找更通用的解
  • “go.tools”的权限被拒绝错误

    当我尝试安装 go 工具时 我的权限被拒绝 usr local go pkg tool linux amd64 cover 我可以接受 因为它是 usr local 目录及需求root使用权 但我的第一个疑问是为什么当我设置时它试图安装在这
  • 直接从一个通道发送到另一个通道

    当从一个通道直接发送到另一个通道时 我偶然发现了令人惊讶的行为 package main import fmt func main my chan make chan string chan of chans make chan chan
  • 如何关闭 gorm 1.20.0 中的数据库实例

    由于我没有在 Close 函数中找到 gorm 实例 任何帮助将不胜感激 dbURI fmt Sprintf user s password s dbname s port s sslmode s TimeZone s username p
  • 如何从 JWT 令牌中提取声明

    我正在使用 dgrijalva jwt go 包 我想从令牌中提取有效负载 但找不到方法 示例 取自 https jwt io https jwt io 对于编码 eyJhbGciOiJIUZI1NiIsInR5cCI6IkpXVCJ9 e
  • 如何使用 GOPATH 的 Samba 服务器位置?

    我正在尝试将 GOPATH 设置为共享网络文件夹 当我进入 export GOPATH smb path to shared folder I get go GOPATH entry is relative must be absolute
  • 如何读取大型平面文件

    我有一个平面文件 其中包含 339276 行文本 大小为 62 1 MB 我试图读入所有行 根据我所拥有的某些条件解析它们 然后将它们插入数据库 我最初尝试使用 bufio Scan 循环和 bufio Text 来获取该行 但缓冲区空间不
  • 为什么 gmail API 以纯文本形式发送 html 电子邮件?

    我正在尝试使用 gmail API 发送 html 电子邮件 但由于某些原因 它会随机以纯文本 文本形式发送电子邮件 谷歌似乎改变了我设置的内容类型标头 这有什么理由吗 电子邮件内容始终完全相同 正如我测试的那样 API 仍处于实验阶段吗
  • 是否可以在 C/C++ 中模仿 Go 接口?

    在 Go 中 如果类型具有接口定义的所有方法 则可以将其分配给该接口变量 而无需显式继承它 是否可以在 C C 中模仿此功能 是的 您可以使用纯抽象类 并使用模板类来包装 实现 抽象类的类型 以便它们扩展抽象类 这是一个简单的示例 incl
  • golang中通道缓冲容量0和1的区别

    我已将通道缓冲区大小设置为零 例如var intChannelZero make chan int 当从intChannelZero将被阻止 直到intChannelZero有价值 另外 我将通道缓冲区大小设置为 1 例如var intCh
  • golang.org 包和标准库之间的区别

    我使用 go 已经有一段时间了 我注意到 Go 标准库 和 golang org x 之间存在重复的包 我的问题是 为什么它们被释放两次 在这两者中 我应该使用哪一个 更新的 规范的等 到目前为止我注意到的一些示例包已发布两次 golang
  • 如何在 Go 中填写 void* C 指针?

    我正在尝试与 Go 中的一些 C 代码交互 使用 cgo 这一直相对简单 直到我遇到这种 相当常见 的情况 需要将指针传递给本身包含指向某些数据的指针的结构 我似乎无法弄清楚如何从 Go 中做到这一点 而不诉诸于将结构的创建放入 C 代码本
  • 如何拥有在标准输出上更新的就地字符串

    我想输出到标准输出并让输出 覆盖 以前的输出 例如 如果我输出On 1 10 我想要下一个输出On 2 10覆盖On 1 10 我怎样才能做到这一点 stdout是一个流 io Writer 您无法修改已写入其中的内容 什么can更改的是该
  • 关于编写惯用的 Golang 的建议

    我正在掌握 Golang 的做事方式 首先是一些示例代码 package main import log os func logIt s string f os OpenFile errors log os O RDWR os O CREA
  • “http:多个response.WriteHeader调用”有什么不好的影响?

    尽管我发现 http 多个响应 WriteHeader 调用 例外 但我的服务器表现良好 此异常不会导致我的服务器出现恐慌或行为异常 我进行了很多搜索 但只找到了如何解决这个问题 没有文档描述异常的不良影响 有人可以帮我找出为什么 http
  • Golang const unsafe.Sizeof

    不明白为什么我可以做到 const OK uint64 0 const OK int unsafe Sizeof uint64 0 但不是这个 const NOK binary Size uint64 0 它的解释在规格 https gol
  • 所有可能的 GOOS 价值?

    如果我做对了 GOOS在编译源代码时确定 为了更好地支持多个操作系统 我感兴趣的是GOOS可能 当然 Go 是开源的 所以它可能有无限的可能性 所以我真正想要的是一个 通用列表 已知值为 windows linux darwin or fr
  • 共享 GOPATH 的良好做法是什么?

    我刚刚开始学习 Go 并阅读现有代码以了解 其他人是如何做的 在这样做时 go 工作空间 的使用 特别是当它与项目的依赖项相关时 似乎无处不在 在处理各种 Go 项目时 使用单个或多个 Go 工作区 即 GOPATH 的定义 的常见最佳实践

随机推荐

  • UEFI基本概念

    TianoCore UEFI EDK2 UEFI Unified Extensible Firmware Interface 用来取代BIOS TianoCore 一个社区 支持UEFI的开源实现 EDK2 一种UEFI的开发环境 UEFI
  • AI大模型有哪些?国内的

    今年相信大家都被ChatGPT刷过屏 因为它太好用了 问它一个问题 它就能回答 可以帮助我们写各种文字 甚至写代码 对于我们的工作有着很大的帮助 国内这半年对于AI这个行业也出现了很多的公司以及产品概念 各家大厂也在抓紧研发 和GPT一样的
  • 读写锁 share_mutex

    实现一个Windows下的共享锁 读写锁 一 作者 tyc611 cublog cn 2008 11 18 在Windows Vista Server 2008之前 Windows没有提供共享锁 通俗称为读写锁 只能靠自己实现 但从Wind
  • java基础面试题系列(71 - 80)

    20200714 by 1z 请你说明HashMap 和 HashTable的区别 1 是否同步 HashMap是非同步的 HashTable是同步的 2 继承体系 HashTable继承自Dictionary HashMap继承自Abst
  • Linux下多进程通信(signal,pipe)

    操作系统实验导航 实验一 银行家算法 https blog csdn net weixin 46291251 article details 115384510 实验二 多级队列调度和多级反馈队列调度算法 https blog csdn n
  • GpuMat ROI

    在引用GpuMat数据的ROI时 需要保证该数据在Gpu 内存中存储是连续的 使用gpu createContinuous创建连续空间 cuda GpuMat dst pyr laplace tmp dst pyr laplace gpu
  • LL(1)文法构造FIRST、FOLLOW、分析表并分析

    一 实验目的 学生运用编译原理的知识在实验技能和方法自行设计实验方案并加以实现 二 使用仪器 器材 计算机一台 操作系统 Windows10 编程软件 Intellij IDEA 三 实验内容及原理 1 实验内容 输入任意一个正确的文法G
  • Windows音量变化通知 - 系统音量监控

    Windows音量变化通知 系统音量监控 Endpoint Volume Controls 1 实现IAudioEndpointVolumeCallback接口 2 主函数 总结 参考 Endpoint Volume Controls 本次
  • 婚姻好不好,嫁给谁很重要

    都说幸福的婚姻是相似的 不幸的婚姻各有各的不幸 事实上 那些不幸的婚姻 追根究底不过都是找错了人 婚姻好不好 关键就在于嫁给谁 因为 值得相信的从来不是感情 而是人 人若靠谱 婚姻便可靠 人若靠不住 婚姻迟早生变 这世上 有的夫妻恩恩爱爱
  • 一次发生在JVM新生代和老年代的GC过程简述

    首先 我们假设程序当前的堆空间的情况如下 然后 程序在运行过程中 开始了我们的第一次YoungGC 年轻代GC 得到如下的图 通过这次的GC 我们的2 3 4对象都被回收了 只有1对象得到了保留 进入了S1 幸存者区 然后我们的程序在运行的
  • Java 通过Soap方式调用WebService接口

    import org apache commons lang3 StringEscapeUtils import org apache http HttpEntity import org apache http client config
  • 短视频seo抖音矩阵源码开发搭建技术解析

    一 短视频seo抖音矩阵源码开发需要考虑以下几个方面 技术选型 选择合适的开发语言 框架和数据库 常用的开发语言有Java PHP等 常用的框架有Spring Django等 常用的数据库有MySQL MongoDB等 服务器的选择 根据应
  • 如何在 NodeJs 中上传、处理和存储文件:分步手册

    存储文件有三种基本方法 1 直接将其存储在数据库中 2 将其存储在文件系统中并将路径保存到数据库 3 将其存储在某些云存储中 例如 Amazon S3 Google Cloud Storage 或 Microsoft Azure Blob
  • 去除自定义AlertDialog黑边

    http blog csdn net mwj 88 article details 45482421 1 现象描述 html view plain copy View view LayoutInflater from getActivity
  • java学习笔记——day1

    java笔记 字面量 变量 数据类型 命名规则 类型转换 运算符operator API 程序的流程控制 数组 字面量 变量 字面量 计算机用来处理数据的 字面量就是告诉程序员 数据在程序中的书写格式 字符 单引号 一个字符 字符串 双引号
  • python+selenium自动化软件测试(第3章):unittes

    3 1 unittest简介 前言 python基础比较弱的 建议大家多花点时间把基础语法学好 这里有套视频 可以照着练习下 http pan baidu com s 1i44jZdb 密码 92fs 熟悉java的应该都清楚常见的单元测试
  • 分层测试(一):什么是分层测试?

    什么是分层测试 分层测试是通过对质量问题分类 分层来保证整体系统质量的测试体系 模块内通过接口测试保证模块质量 多模块之间通过集成测试保证通信路径和模块间交互质量 整体系统通过端到端用例对核心业务场景进行验证 用户体验通过手工测试确保无妨碍
  • Unity开发(2)建片草地

    文章目录 1 简述 2 创建 2 1 创建项目 2 2 进入开发窗体 3 建个地面 3 1 新建地面 3 2 调整地面大小 3 3 添加草地 3 3 1 初识Unity图片资源 3 3 2 添加图片资源 3 3 3 修改图片在场景中大小 1
  • C语言入门知识1(零基础新手适用)

    C语言入门知识1 零基础新手适用 程序语言 1 机器语言 机器语言是低级语言 是用01码来编写的二进制代码语言 2 汇编语言 汇编语言也是低级语言 是用英文字母和符号串编写的 3 高级语言 由于汇编语言依赖于硬件体系且符合较多 为了方便高级
  • Go中 defer的使用

    文章目录 简介 示例 使用场景 捕获异常 文件操作 简介 defer 是 Golang 中的一个非常有用的关键字 它用于注册延迟调用 也就是一个函数的执行被延迟到调用它的函数返回之后 常用于资源清理 异常处理等场景 示例 defer 是注册