news 2026/6/9 6:47:46

Go Defer语句详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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 代码的重要一步。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/8 14:51:33

基于Dify部署多语言GPT-SoVITS合成系统的架构设计

基于Dify部署多语言GPT-SoVITS合成系统的架构设计 在智能语音技术快速演进的今天,个性化声音不再只是影视明星或大公司的专属资源。随着开源模型和低代码平台的成熟,普通人仅凭几分钟录音就能拥有“数字分身”的时代已经到来。尤其是在客服播报、有声内容…

作者头像 李华
网站建设 2026/6/7 18:29:57

LobeChat能否实现AI艺术品鉴定?收藏价值评估模型构建

LobeChat能否实现AI艺术品鉴定?收藏价值评估模型构建 在拍卖行的灯光下,一幅水墨虾蟹图静静陈列。专家俯身细看笔触走势、印章位置与纸张泛黄程度,几分钟后给出结论:“齐白石真迹,估价300万左右。”这样的场景正悄然发…

作者头像 李华
网站建设 2026/6/8 14:57:55

GPT-SoVITS训练过程中显存不足怎么办?优化建议

GPT-SoVITS训练显存不足?这5个实战优化策略让你在12GB显卡上跑起来 你有没有试过满怀期待地启动 GPT-SoVITS 训练,结果刚进第一个 epoch 就弹出 CUDA out of memory 的红色警告?别急,这不是你的数据有问题,也不是代码写…

作者头像 李华
网站建设 2026/6/8 14:41:57

LobeChat能否支持3D模型预览?工业设计领域应用前景

LobeChat能否支持3D模型预览?工业设计领域应用前景 在智能制造与协同设计日益普及的今天,工程师们不再满足于AI助手只能“读文档、答问题”。他们希望AI能真正“看懂”设计图纸,甚至理解三维结构——比如上传一个STL文件后,直接问…

作者头像 李华
网站建设 2026/6/8 18:48:34

基于Android的高校校车订座系统的设计与实现(源码+lw+部署文档+讲解等)

课题介绍本课题聚焦高校校车乘坐无序、座位资源浪费、乘车信息不透明的痛点,设计实现基于 Android 的高校校车订座系统。系统以 Java 为核心开发语言,基于 Android 原生框架搭建移动端应用,搭配轻量后端服务架构,处理校车班次管理…

作者头像 李华