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

相关推荐
AI人工智能+电脑小能手5 分钟前
【大白话说Java面试题】【Java基础篇】第20题:HashMap在计算index的时候,为什么要对数组长度做减1操作
java·开发语言·数据结构·后端·面试·哈希算法·hash-index
阿丰资源1 小时前
基于Spring Boot的新闻推荐系统(源码+数据库+文档)
数据库·spring boot·后端
Gopher_HBo1 小时前
Disruptor消费源码分析
后端
审判长烧鸡1 小时前
GO错误处理【2】os.Exit(1)/panic/返回err的应用场景
go·异常处理·panic
千寻girling2 小时前
滑动窗口刷了快一个月(26天)了 , 还没有刷完. | 含(操作系统学什么的Java 后端)
java·开发语言·javascript·c++·人工智能·后端·python
thatway19892 小时前
太奶也能看懂的 M100 芯片故事
后端
审判长烧鸡2 小时前
GO时区【4】PostgreSQL时区
postgresql·go
木雷坞2 小时前
K8s GPU 冷启动:把镜像预热从发布里拆出来
后端
渐儿2 小时前
Dify 插件机制详解
后端
渐儿2 小时前
Spring Boot 异步并发实现原理详解
后端