go语言中defer的注意事项

defer介绍

Go语言中的defer语句会将其后面跟随的语句进行延迟处理。在defer归属的函数即将返回时,将延迟处理的语句按defer定义的逆序进行执行,也就是说,先被defer的语句最后被执行,最后被defer的语句,最先被执行。

举个例子:

func main() {
	fmt.Println("start")
	defer fmt.Println(1)
	defer fmt.Println(2)
	defer fmt.Println(3)
	fmt.Println("end")
}

输出结果:

start
end
3
2
1

由于defer语句延迟调用的特性,所以defer语句能非常方便的处理资源释放问题。比如:资源清理、文件关闭、解锁及记录时间等。

defer执行时机

在Go语言的函数中return语句在底层并不是原子操作,它分为给返回值赋值和RET指令两步。而defer语句执行的时机就在返回值赋值操作后,RET指令执行前。具体如下图所示:defer执行时机

注意事项

package main

import "fmt"

func calc(index string, a, b int) int {
	ret := a + b
	fmt.Println(index, a, b, ret)
	return ret
}

func main() {
	x := 1
	y := 2
	defer calc("AA", x, calc("A", x, y))
	x = 10

	defer calc("BB", x, calc("B", x, y))
	y = 20
}

image-20230315152302728

程序遇到defer的时候, 会先将defer的语句注册到一个类栈式结构中, 遵循先进后出的原则, 当程序走完对应方法最后一行或者 panic 的时候, 会执行defer语句。

内部的值已经定义,执行时会直接使用,在defer后面改变值也不会改变defer内部的执行。

defer 使用的局部变量一定要先确定, 也就是说当它注册的时候, 使用的是局部变量的值拷贝, 后面变量的修改不会影响到 当前 defer 的使用。

posted @   熟稔于纸  阅读(26)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示