当前位置: 首页 > news >正文

Go的defer原理

Go 的 defer 原理

defer 是 Go 语言中的一个关键字,用于延迟执行一个函数调用。它通常用于处理资源释放、连接关闭等操作,确保这些操作在函数返回之前执行。
在这里插入图片描述


1. 什么是 defer

defer 关键字用于延迟执行一个函数调用,直到包含它的函数返回。无论函数是正常返回还是发生异常(如 panic),defer 语句都会被执行。

特点
  • 延迟执行defer 语句中的函数调用会在当前函数返回之前执行。
  • 栈式执行:多个 defer 语句会按照后进先出(LIFO)的顺序执行。
  • 资源管理:常用于释放资源、关闭连接等操作。

2. defer 的原理

实现机制

Go 编译器会将 defer 语句转换为一个延迟调用链表。每个 defer 语句会被添加到链表的头部,函数返回时从链表头部开始依次执行。

执行时机
  • 函数返回时:无论是通过 return 返回还是发生 panicdefer 语句都会被执行。
  • 栈式顺序:多个 defer 语句按照后进先出的顺序执行。

3. defer 的使用场景

资源释放

defer 常用于确保资源(如文件、网络连接、锁等)在函数返回时被正确释放。

错误处理

defer 可以与 recover 结合使用,用于捕获和处理 panic

日志记录

defer 可以用于记录函数的执行时间或状态。


4. defer 的常见坑

坑 1:defer 的参数立即求值

defer 语句中的函数参数会在 defer 语句执行时立即求值,而不是在函数调用时求值。

坑 2:defer 的执行顺序

多个 defer 语句会按照后进先出的顺序执行,可能导致意外的行为。

坑 3:defer 与返回值

如果 defer 语句修改了函数的返回值,可能会导致意外的结果。

坑 4:defer 的性能开销

defer 语句会引入额外的性能开销,尤其是在高频调用的函数中。


函数调用
执行 defer 语句
将 defer 函数添加到延迟调用链表
函数返回
从链表头部开始执行 defer 函数
函数结束
使用实例

资源释放

package mainimport ("fmt""os"
)func main() {file, err := os.Open("example.txt")if err != nil {fmt.Println("Error opening file:", err)return}defer file.Close() // 确保文件在函数返回时关闭// 文件操作fmt.Println("File opened successfully")
}

错误处理

package mainimport "fmt"func main() {defer func() {if r := recover(); r != nil {fmt.Println("Recovered from panic:", r)}}()panic("Something went wrong!")
}

日志记录

package mainimport ("fmt""time"
)func main() {start := time.Now()defer func() {fmt.Println("Function execution time:", time.Since(start))}()// 模拟耗时操作time.Sleep(2 * time.Second)
}
http://www.lryc.cn/news/525576.html

相关文章:

  • Windows 下本地 Docker RAGFlow 部署指南
  • 专题三_穷举vs暴搜vs深搜vs回溯vs剪枝_全排列
  • 【IEEE Fellow 主讲报告| EI检索稳定】第五届机器学习与智能系统工程国际学术会议(MLISE 2025)
  • 华为E9000刀箱服务器监控指标解读
  • 【LC】2544. 交替数字和
  • QT QTreeWidget控件 全面详解
  • 欧几里得算法求最小公倍数和最大公约数
  • Selenium配合Cookies实现网页免登录
  • DeepSeek R1模型解读与使用
  • Windows电脑不小心点击了关机,关机过程中如何阻止
  • CNN-GRU卷积门控循环单元时间序列预测(Matlab完整源码和数据)
  • 【吉林乡镇界】面图层shp格式arcgis数据乡镇名称和编码wgs84无偏移内容测评
  • fpga学习入门 串口rs232回环
  • 智启未来,AI筑梦科技新星”------华清远见成都中心2025冬令营圆满结束
  • 接上篇基于Alertmanager 配置钉钉告警
  • DDD - 如何设计支持快速交付的DDD技术中台
  • JAVA与数据结构-线性表
  • C++|开源日志库log4cpp和glog
  • React Context 实现全局组件注册
  • 基于AutoDL云计算平台+LLaMA-Factory训练平台微调本地大模型
  • strdup 函数
  • 2.9/Q2,Charls最新文章解读!
  • 【未完成】springboot项目实现扫码登录相关逻辑
  • html、js、css实现爱心效果
  • 【前端】Hexo 建站指南
  • OpenStack基础架构
  • 1905电影网中国地区电影数据分析(一) - 数据采集、清洗与存储
  • IPhone16 Plus 设备详情
  • 埃氏算法C++实现: 快速输出质数( 素数 )
  • 后端的config包中的常用配置