当前位置: 首页 > 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.jsqmd.com/news/99996/

相关文章:

  • npm安装常见错误及解决方案汇总(YOLO专用)
  • 2025年国产电脑操作系统推荐:银河麒麟为何成为党政机关首选?
  • 2025少儿编程机构实测:3家高口碑品牌+5个避坑技巧,家长直接抄作业 - 品牌测评鉴赏家
  • Git安装配置指南:集成清华镜像提升TensorFlow项目克隆效率
  • LobeChat能否生成KPI指标?绩效考核智能化
  • Flutter 2025 国际化与本地化工程:从多语言到文化适配,打造真正全球化的应用
  • AI证书口碑好排名
  • 2025年高性价比在线少儿编程机构测评:这5家凭什么让家长放心买单? - 品牌测评鉴赏家
  • 记一次大屏某一处图像采集接口异常导致该页其他图表都无法显示问题解决
  • LobeChat能否支持梦境解析?睡眠记录与心理象征意义探讨
  • LobeChat支持拖拽上传文件吗?实测多种格式兼容性
  • 三大在线少儿编程机构深度对比与选择指南 - 品牌测评鉴赏家
  • LobeChat能否接入语音合成TTS?全流程语音交互实现
  • 2025年信誉好的工业设计企业排行榜,新测评精选工业设计机构 - 工业推荐榜
  • vue基于Springboot框架大学生竞赛辅导管理系统设计与实现_979lg660
  • 基于Dify部署多语言GPT-SoVITS合成系统的架构设计
  • 2025年薄壁轴承加工厂推荐:哪家更值得选、维护更方便、工艺 - mypinpai
  • 关于Windows 11 家庭中文版 25H2中ensp无法启动路由器,报40错的解决方法
  • Flutter:在代码与像素之间,重建移动开发的诗意
  • 解决‘此扩展程序不再受支持,因此已停用’问题:PaddlePaddle浏览器插件适配建议
  • 开源不输商用!LobeChat媲美ChatGPT的用户体验实测
  • TensorFlow-GPU环境搭建与PyCharm配置指南
  • 2025年湖北岩棉净化板供应商排名:硅岩净化板与机制净化板安 - myqiye
  • 网安零基础必冲!upload-labs 文件上传漏洞保姆级通关教程
  • 2025年高性价比少儿编程机构推荐,这几家非知名品牌值得关注 - 品牌测评鉴赏家
  • 2025岩棉净化板定制TOP5权威推荐:玻镁硫氧镁净化板厂家 - 工业品牌热点
  • 唐诗容斥解CF2170E
  • FLUX.1-ControlNet自定义控制模式全解
  • PC板生产厂家推荐榜:29年经验 + 70多品种全覆盖(厂家直销) - 品牌排行榜
  • vue基于Springboot框架的宠物之家领养寄养救助商城管理系统h1ypq0zm