You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

defer是否在函数返回后执行?一段Go语言代码返回值不符合预期的原因排查

为什么Go代码的输出和预期不符?

嘿,这个问题其实戳中了Go语言里return和defer的执行细节,我来给你一步步理清楚:

1. 为什么会打印出0?

你遇到的核心问题是Go的return语句不是原子操作,它的执行分为三个关键步骤:

  • 第一步:先计算要返回的具体值,把这个值存入一个专门的临时返回变量里;
  • 第二步:执行当前函数中所有已声明的defer语句;
  • 第三步:把临时返回变量的值作为函数最终返回值返回。

放到你的代码里看:

  • 当example()执行到return i时,先读取了全局变量i的当前值(初始是0),并把这个0存进了临时返回变量;
  • 随后才执行defer的匿名函数:虽然它把全局变量i改成了1,但这个修改不会影响已经提前存好的临时返回变量;
  • 所以example()最终返回的是临时变量里的0,main中第一个fmt.Println自然就输出0了。

2. defer是在函数返回后执行吗?

绝对不是,defer的执行时机是函数真正返回之前——也就是在return的“计算返回值”步骤之后,“返回结果”步骤之前。

我们把你的代码完整走一遍流程,就能看得更清楚:

  1. 全局变量i默认初始化为0;
  2. main函数调用example():
    • 先执行fmt.Println("first"),输出first;
    • 执行return i:计算得到i=0,存入临时返回变量;
    • 执行defer匿名函数:输出defer,并把全局变量i改成1;
    • example()返回临时变量的0,main中第一个fmt.Println输出0;
  3. main执行第二个fmt.Println(i),此时全局变量i已经被defer修改为1,所以输出1。

如果你想让example()返回1,可以改成返回指针类型,这样defer中修改原变量就能影响返回值:

package main
import (
	"fmt"
)
var i int
func example() *int {
	defer func() {
		fmt.Println("defer")
		i = 1
	}()
	fmt.Println("first")
	return &i
}
func main() {
	fmt.Println(*example())
	fmt.Println(i)
}

这段代码的输出就会和你最初的预期一致。

内容的提问来源于stack exchange,提问作者Vitor Falcão

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 16:12:28