defer在go中的执行顺序是后进先出(lifo),1.遇到defer语句时,函数调用会被压入栈中,2.当前函数返回前,栈顶的defer函数依次弹出执行;例如连续两个defer,后写的先执行。defer参数在注册时求值,如i++不影响已保存的值。return前会执行defer,可能影响命名返回值的结果。注意事项包括:避免循环中频繁使用defer、不在defer中做耗时操作、注意作用域及副作用。
在 Golang 中,defer 是一个非常实用的关键字,用来延迟执行某个函数调用,通常用于资源释放、锁的释放等场景。但很多人刚接触时会对其执行顺序感到困惑,尤其是当多个 defer 出现的时候。
其实,只要理解 defer 的底层机制是基于栈结构实现的,它的执行顺序就很容易理解了。
Golang 在遇到 defer 语句时,并不会立即执行对应的函数,而是将其压入一个函数调用栈中。等到当前函数即将返回之前,才会从栈顶开始依次弹出并执行这些被推迟的函数调用。
立即学习“go语言免费学习笔记(深入)”;
举个简单的例子:
func main() { defer fmt.Println("first") defer fmt.Println("second") fmt.Println("hello world") }
输出结果是:
hello world second first
虽然两个 defer 是按顺序写的,但由于它们被压入栈中,执行顺序就是反过来的。这和我们日常理解的“最后写的先执行”是一致的。
一个容易忽略的细节是:defer 后面的函数参数是在 defer 被执行时就完成求值的,而不是等到真正执行该函数时才计算。
看个例子:
func demo() { i := 0 defer fmt.Println(i) i++ }
这段代码输出的是 0,不是 1。因为 i 的值在 defer 执行时就已经确定为 0 了,后续的 i++ 并不会影响已经保存下来的值。
所以记住一点:defer 注册时就完成了参数求值。
很多人以为 return 之后就不能再执行 defer 了,实际上并不是这样。Go 在函数返回前,会先处理所有注册好的 defer 调用,然后再真正退出函数。
例如:
func f() int { var i int defer func() { i++ }() return i }
这个函数返回的其实是 1,而不是 0。因为 return i 的值已经被准备好了,但在返回前执行了 defer,修改了 i 的值。
这种情况说明:defer 可以影响带命名返回值的函数的结果。
总的来说,理解 defer 的执行顺序并不难,关键在于它背后的“栈结构”机制。掌握了这一点,很多看似奇怪的行为其实都合情合理。
基本上就这些,不复杂但容易忽略。
以上就是Golang defer关键字的执行顺序 结合栈结构解释延迟调用机制的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号