【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 = 注册一个"收尾操作",在函数退出前按栈顺序执行
相关推荐
ltl5 小时前
Transformer 整体架构:一张图看懂
后端
Highcharts.js5 小时前
倒置百分比堆叠面积图表示列详解|Highcharts大气成分图表代码
开发语言·信息可视化·highcharts·图表开发·面积图·图表示例·推叠图
ltl5 小时前
Decoder 详解:为什么它天生适合生成
后端
csdn_aspnet5 小时前
C语言 Lomuto分区算法(Lomuto Partition Algorithm)
c语言·开发语言·算法
晨曦中的暮雨5 小时前
4.15腾讯 CSIG云服务产线 一面
java·开发语言
ltl5 小时前
Encoder 详解:6 层堆叠到底在做什么
后端
程序员cxuan5 小时前
微信读书官方发了 skills,把我给秀麻了。
人工智能·后端·程序员
存在morning5 小时前
【GO语言开发实践】二 GO 并发快速上手
大数据·开发语言·golang
未若君雅裁6 小时前
Spring AOP、日志切面与声明式事务原理
java·后端·spring
zhangxingchao6 小时前
AI应用开发六:企业知识库
前端·人工智能·后端