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

Go语言中runtime.deferreturn是否会被调用?基于汇编代码的疑问

关于Go函数中defer对应汇编代码的疑问

我在查看包含defer的Go函数末尾的汇编代码时,看到如下内容:

0x000000000047e1a0 <+256>:   callq  *%rsi
   0x000000000047e1a2 <+258>:   movb   $0x0,0x7(%rsp)
   0x000000000047e1a7 <+263>:   mov    0x748(%rsp),%rdx
   0x000000000047e1af <+271>:   mov    (%rdx),%rbx
   0x000000000047e1b2 <+274>:   callq  *%rbx
   0x000000000047e1b4 <+276>:   mov    0x750(%rsp),%rbp
   0x000000000047e1bc <+284>:   add    $0x758,%rsp
   0x000000000047e1c3 <+291>:   retq
   0x000000000047e1c4 <+292>:   callq  0x42ea40 <runtime.deferreturn>
   0x000000000047e1c9 <+297>:   mov    0x750(%rsp),%rbp
   0x000000000047e1d1 <+305>:   add    $0x758,%rsp
   0x000000000047e1d8 <+312>:   retq
   0x000000000047e1d9 <+313>:   callq  0x458900 <runtime.morestack>

可以看到,调用runtime.deferreturn之前存在一条retq指令,因此看起来该函数永远不会被调用。请问我的理解是否正确?


你的理解不正确,runtime.deferreturn会被正常调用

原因如下:

  • Go编译器会为带defer的函数,在所有可能的退出路径都插入runtime.deferreturn的调用逻辑,包括正常return、panic恢复后的退出等场景。你看到的<+291>处的retq只是函数的常规退出分支,并非唯一路径。
  • 当函数因panic触发栈展开、或者通过某些异常分支跳转时,程序会执行到<+292>位置的runtime.deferreturn调用,用来执行所有注册的defer函数。
  • 另外,<+313>处的runtime.morestack是栈扩容处理逻辑,当函数运行中需要扩展栈空间时,会跳转到这里执行,处理完成后也可能回到runtime.deferreturn的执行路径。
  • Go编译器会做defer优化,但只要函数里声明了defer,就一定会在对应场景下触发runtime.deferreturn,不会出现永远不调用的情况。

内容的提问来源于stack exchange,提问作者linlin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 08:57:14