Golang defer使用
- 1. defer的执行顺序类似于栈,“后进先出”,也就是最先defer的语句最后执行,而最后defer的最先执行
- 2. defer和return的坑
- 3. defer注册要延迟执行的函数时该函数所有的参数都需要确定其值
学习于https://www.liwenzhou.com/posts/Go/function/的文章
1. defer的执行顺序类似于栈,“后进先出”,也就是最先defer的语句最后执行,而最后defer的最先执行
func main() {
defer fmt.Println("1")
defer fmt.Println("2")
defer fmt.Println("3")
}
//控制台打印
3
2
1
2. defer和return的坑
首先return操作并不是原子操作,他分为2步:一是给返回值赋值,二是return返回值。如果函数中有defer的话,那么defer会被夹杂在2步中间,也就是先给返回值赋值,执行defer,return返回值。
func main() {
fmt.Println("匿名返回:", a()) //5
fmt.Println("有名返回:", b()) //6
}
// 匿名返回值
func a() int {
x := 5
defer func() {
x++
}()
return x
}
// 有名返回值
func b() (x int) {
x = 5
defer func() {
x++
}()
return x
}
使用匿名返回函数,控制台打印的是5,这是执行return x时,首先定义 返回值=x(非同一个变量),然后执行defer x++,最后return返回值,而此时返回值已经=x,x++不会再影响返回值了,所以返回的是5。
使用有名返回时,就指定了返回值=x(同一个变量,内存地址相同),所以x++后,返回的值也++了。
3. defer注册要延迟执行的函数时该函数所有的参数都需要确定其值
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
}
第一次注册defer calc("AA", x, calc("A", x, y))时,会执行里面的calc("A", x, y),此时x=1,y=2,所以先打印,
A 1 2 3
于是defer calc("AA", x, calc("A", x, y))中的参数被确定,是defer calc("AA", 1, 3)
接下来x=10,y没变,仍等于2,执行defer calc("BB", x, calc("B", x, y)),执行calc("B", x, y),打印
B 10 2 12
于是defer calc("BB", x, calc("B", x, y))中的参数被确定,是defer calc("BB", 10, 12)
然后按照defer顺序执行,先执行defer calc("BB", 10, 12),再执行defer calc("AA", 1, 3),所以打印
BB 10 12 22
AA 1 3 4
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!