golang中defer的小坑

我们都知道,defer往往在函数的最后执行,遵循先进后出 原则,在return函数写入返回值后执行,而且传入的形参会立即读入,后续修改对其无影响

Go 函数返回过程完整流程

当一个函数执行到 return 语句时,执行顺序是

  1. 计算 return 后的表达式(如果有的话),将结果赋值给返回值;
  2. 执行所有的 defer 语句(按照后进先出 LIFO 的顺序);
  3. 函数真正返回(携带返回值)

下面来看这三个案例

go 复制代码
package main
​
import "fmt"
​
func Func1() int {
    a := 0
    defer func() {
        a++
    }()
    return a
}
​
func Func2() (a int) {
    a = 0
    defer func() {
        a++
    }()
    return
}
​
func Func3() *int {
    a := new(int)
    *a = 0
    defer func() {
        *a++
    }()
    return a
}
​
func main() {
    fmt.Println(Func1())
    fmt.Println(Func2())
    fmt.Println(*Func3())
}

输出结果为

复制代码
0 1 1

案例分析

这三个究竟有什么区别呢?

案例一:

  1. 首先,我们获得a的值0,然后会重新赋值一份给临时的返回槽(slot)当中
  2. 然后,调用defer,修改局部变量a为1,但是a已被copy一份到返回槽,所以重新赋值没有用
  3. 返回0

案例二:

  1. 首先,我们获得a的值0,然后会重新赋值一份给临时的返回槽(slot)当中
  2. 然后defer修改了引用类型a的值
  3. 返回1

案例三:

与案例一相似,但是传递的是指针,能修改地址中存储的值,所以返回的是1

相关推荐
Goboy31 分钟前
Java 使用 FileOutputStream 写 Excel 文件不落盘?
后端·面试·架构
Goboy42 分钟前
讲了八百遍,你还是没有理解CAS
后端·面试·架构
麦兜*1 小时前
大模型时代,Transformer 架构中的核心注意力机制算法详解与优化实践
jvm·后端·深度学习·算法·spring·spring cloud·transformer
树獭叔叔1 小时前
Python 多进程与多线程:深入理解与实践指南
后端·python
阿华的代码王国1 小时前
【Android】PopupWindow实现长按菜单
android·xml·java·前端·后端
卡尓1 小时前
Yii 中多版本控制器的实现
后端
用户7129092383072 小时前
学习使用Trae AI 编程助手
后端
码事漫谈2 小时前
深入浅出理解WaitForSingleObject:Windows同步编程核心函数详解
后端
云辇1032 小时前
[Rust]Influxdb初体验
后端
阿星AI工作室2 小时前
扣子可以发布到小米搞钱了!手把手教程来了丨coze开发者瓜分亿级流量池指南
前端·人工智能·后端