【go】 Go语言中的 defer:从入门到理解底层机制(讲透版)

👨‍💻 关于作者:会编程的土豆

"不是因为看见希望才坚持,而是坚持了才看见希望。"

你好,我是会编程的土豆,一名热爱后端技术的Java学习者。

📚 正在更新中的专栏:

💕作者简介:后端学习者

defer 是 Go 里一个非常"有味道"的关键字。

很多人一开始只会用,但其实不理解执行顺序和坑点,很容易写错代码

这篇直接帮你彻底搞懂。


一、defer 是什么?

一句话:

复制代码
defer = 延迟执行,在函数结束前执行

最简单例子

Go 复制代码
func main() {
    fmt.Println("start")

    defer fmt.Println("defer")

    fmt.Println("end")
}

输出

复制代码
start
end
defer

核心结论

复制代码
defer 一定在函数 return 之前执行

二、多个 defer 的执行顺序(重点)


示例

Go 复制代码
func main() {
    defer fmt.Println(1)
    defer fmt.Println(2)
    defer fmt.Println(3)
}

输出

复制代码
3
2
1

结论

复制代码
defer 是栈结构(后进先出 LIFO)

👉 类比:

复制代码
像压栈 → 出栈

三、defer + return(高频考点)


示例

Go 复制代码
func test() int {
    defer fmt.Println("defer")
    return 10
}

执行顺序(非常重要)

复制代码
1. 计算 return 的值
2. 执行 defer
3. 返回

四、经典陷阱:defer 修改返回值


示例1(无效修改)

Go 复制代码
func test() int {
    a := 10
    defer func() {
        a = 20
    }()
    return a
}

返回值

复制代码
10

为什么?

复制代码
return a 已经把值拷贝走了

示例2(有效修改)

Go 复制代码
func test() (a int) {
    a = 10
    defer func() {
        a = 20
    }()
    return
}

返回值

复制代码
20

关键区别

复制代码
✔ 命名返回值 → defer 可以修改
✔ 普通返回值 → defer 修改不了

五、defer + 参数(超级容易错)


示例

Go 复制代码
func main() {
    a := 10

    defer fmt.Println(a)

    a = 20
}

输出

复制代码
10

原因

复制代码
defer 在注册时就把参数"拷贝"了

对比:闭包写法

Go 复制代码
defer func() {
    fmt.Println(a)
}()

输出

复制代码
20

结论

复制代码
defer参数:立即求值
defer函数:延迟执行

六、defer 的典型应用场景


1. 关闭资源(最重要)

Go 复制代码
file, _ := os.Open("test.txt")
defer file.Close()

2. 解锁

Go 复制代码
mu.Lock()
defer mu.Unlock()

3. 计时

Go 复制代码
start := time.Now()
defer func() {
    fmt.Println(time.Since(start))
}()

七、defer 的底层理解(面试加分)


本质

复制代码
defer = 把函数压入一个栈

执行时机

复制代码
函数 return 前,按栈顺序执行

八、性能问题(进阶)


早期 Go

复制代码
defer 较慢

现在(Go 1.20+)

复制代码
优化后基本可以放心使用

九、常见坑总结(必须记住)


1️⃣ defer 顺序是反的

复制代码
后写先执行

2️⃣ 参数是立即计算

复制代码
defer fmt.Println(a)  // 立即拷贝

3️⃣ 命名返回值可以被修改

复制代码
func f() (a int)

4️⃣ defer 不要写在循环里(可能性能问题)


十、一句话总结

复制代码
defer = 注册一个"收尾操作",在函数退出前按栈顺序执行
相关推荐
动能小子ohhh15 分钟前
DocForge平台的设计与开发--文件上传接口的实现
开发语言·人工智能·python·langchain·ocr·fastapi
满天星830357718 分钟前
【Qt】信号和槽(二) (自定义信号和槽)
开发语言·数据库·qt
超哥--1 小时前
B站视频内容智能分析系统(三):B站视频自动采集
java·开发语言·音视频·ai编程
小村儿1 小时前
连载13- 内部Tools,Claude Code 怎么真正"动"你的代码
前端·后端·ai编程
IT_陈寒1 小时前
Python的线程池把我坑惨了,原来异步不是万能的
前端·人工智能·后端
夏语灬1 小时前
cryptography:Python 密码学标准库的终极选择
开发语言·python·密码学
郑洁文1 小时前
基于SpringBoot的商品仓库管理系统的设计与实现
java·spring boot·后端·仓库管理系统·商品仓库管理系统
Jun6261 小时前
QT(19)-VISA控制仪器
开发语言·qt
ANnianStriver1 小时前
PetLumina 07 — 宠物管理升级与 JavaScript 大数精度修复
开发语言·javascript·ai编程·宠物
该用户已不存在1 小时前
这9款开发工具夯爆了,用了都说好
后端·程序员·全栈