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

Go Defer语句详解

在实际编程中,我们经常需要清理一些资源,比如打开的文件数据库连接等。当程序不再使用这些资源时,及时关闭它们非常重要,否则可能会造成:

  • 内存泄漏

  • 文件或连接被长期占用

  • 其他程序无法访问这些资源

在本节中,我们将学习 Go 语言中的一个特殊语句,它可以帮助我们在程序执行过程中自动清理资源,让代码更加简洁、安全、不易出错,并且让“关闭资源”的代码紧挨着“打开资源”的代码,提高可读性。


defer语句

在 Go 中,我们使用defer语句延迟执行一个函数,直到包含它的函数即将返回时才执行。


defer的基本用法

下面是一个最基础的例子:

packagemainimport"fmt"funcmain(){deferfmt.Println("Printed second! 2")fmt.Println("Printed first! 1")}

输出结果:

Printed first!1Printed second!2

代码解释

虽然"Printed second! 2"在代码中先出现,但它并没有先输出。

这是因为:

任何使用defer修饰的语句,都会等到当前函数执行结束时才被调用。


多个defer语句

在 Go 程序中,可以有多个defer语句。
当存在多个defer时,它们会被当作一个栈来管理

来看下面的例子:

packagemainimport"fmt"funcmain(){deferfmt.Println("🐥")// 第 1 个 deferdeferfmt.Println("🐣")// 第 2 个 deferdeferfmt.Println("🥚")// 第 3 个 defer}

输出结果:

🥚 🐣 🐥

代码解释

  • 🐥最先被 defer 的,但最后执行

  • 🥚最后被 defer 的,却最先执行

这说明:

defer的执行顺序是后进先出(LIFO,Last In First Out)

可以把它理解为一个栈结构

defer🐥defer🐣defer🥚 ← 先执行

多个函数中的defer

当多个函数中都包含defer时,需要注意:

defer只在它所在的函数结束时才会执行

来看下面的例子:

packagemainimport"fmt"funcgreeting(){deferfmt.Println("Printed after Hello, JB Academy!")// 2fmt.Println("Hello, JB Academy!")// 1}funcmain(){deferfmt.Println("Printed after the main() function is completed.")// 4greeting()fmt.Println("Printed after calling the greeting() function.")// 3}

输出结果:

Hello,JB Academy!Printed after Hello,JB Academy!Printed after calling thegreeting()function.Printed after themain()function is completed.

代码解释

执行顺序如下:

  1. greeting()内部先打印
    Hello, JB Academy!

  2. greeting()结束
    → 执行其defer

  3. 回到main()
    → 打印普通语句

  4. main()结束
    → 执行main()中的defer

结论:

每个函数中的defer,都会在该函数结束时立即执行,与其他函数互不影响。


作用域中的defer

再看一个关于作用域的例子:

funcscopedDefer(){n:=0deferfunc(){fmt.Println("n =",n,"- first deferred print")}(){deferfunc(){fmt.Println("n =",n,"- second deferred print")}()n++// n = 1}n++// n = 2}

输出结果:

n=2-second deferredprintn=2-first deferredprint

代码解释

  • 两个defer都在scopedDefer()函数中

  • 即使其中一个写在代码块{}内,它们也不会提前执行

  • 都要等到scopedDefer()函数结束

  • 执行时,变量n的值已经变成2

说明:

defer的执行时间与函数结束有关,而不是代码块结束。


使用defer关闭文件(最常见用法)

defer最常见、最重要的用途之一,就是释放资源,例如关闭文件。

packagemainimport("fmt""log""os")funcmain(){file,err:=os.Create("test.txt")iferr!=nil{log.Fatal(err)}deferfile.Close()// 程序结束前自动关闭文件if_,err:=fmt.Fprintln(file,"Hello World!");err!=nil{log.Fatal(err)}}

代码解释

  • os.Create()创建并打开文件

  • defer file.Close()保证函数结束前文件一定会被关闭

  • 即使中途return或发生错误,也不会忘记关闭文件


为什么要用defer关闭资源?

使用defer有两个明显优点:

1. 防止忘记关闭资源

如果以后给函数增加新的return路径,也不用担心遗漏Close()

2. 代码更清晰

“打开资源”和“关闭资源”写在一起,可读性更好,而不是把Close()放在函数结尾。


总结

在本节中,主要内容包括:

  • defer会在当前函数返回前执行

  • 多个defer后进先出(LIFO)顺序执行

  • defer的作用域是函数级别

  • defer最常见的用途是关闭文件、释放资源

掌握defer是写出安全、优雅 Go 代码的重要一步。

http://www.cnnetsun.cn/news/88518.html

相关文章:

  • 事务拦截器TransactionInterceptor
  • Qwen3-VL-30B 4bit量化版发布:单卡部署突破
  • FLUX.1-ControlNet自定义控制模式全解
  • Windows server 2019 离线安装docker容器
  • springboot基于uniapp的有机农产品商城电商平台_4747f8w7-小程序
  • 用Dify构建文生视频工作流:从输入到输出
  • 基于Android的高校教室预约管理平台系统(源码+lw+部署文档+讲解等)
  • 开源不输商用!LobeChat媲美ChatGPT的用户体验实测
  • 十三、Kafka基础环境实战
  • EmotiVoice 安装与环境配置指南
  • LobeChat能否实现AI专利检索?技术创新辅助工具开发
  • vue基于spring boot的乡村民宿预订周边旅游管理系统
  • 网安零基础必冲!upload-labs 文件上传漏洞保姆级通关教程
  • vue基于Springboot框架 新能源充电桩报修管理系统
  • v3基于SpringBoot的酒店管理系统
  • Git安装Windows版本并配置清华镜像用于TensorFlow贡献开发
  • Langchain-Chatchat 0.3.1 Windows本地部署指南
  • 私有云ACK:企业智能化转型的安全基座与算力引擎
  • Docker部署Qwen3-14B及GPU加速实战
  • SWIR相机
  • vLLM 0.11.0 发布:全面移除 V0 引擎,性能与多模态支持再升级
  • 从零开始:使用Git安装TensorRT及其依赖组件
  • 模块十八.集合
  • FLUX.1-dev服装生成LoRA模型体验
  • 使用nexus3搭建自己的制品服务器
  • 38、Linux 邮件与网页浏览实用指南
  • 41、互联网服务实用指南
  • LLaMA-Factory微调与模型中断续训实战
  • GitHub项目实践:Fork并定制你的个性化Anything-LLM前端界面
  • pythonstudy Day37