前言
defer
是Golang中一个常用的关键字,通常用来做一些收尾工作。比如开启了一个东西,就顺手defer
中关闭。对于面试,defer
也算一个高频考点,尤其是他的许多个坑,因此本文主要复习一下defer的用法
。
多个defer
的执行顺序
通常来说,defer
是在程序的最后才执行。当多个defer
出现时,遵循 栈 的先入后出顺序执行。
前言
defer
是Golang中一个常用的关键字,通常用来做一些收尾工作。比如开启了一个东西,就顺手defer
中关闭。对于面试,defer
也算一个高频考点,尤其是他的许多个坑,因此本文主要复习一下defer的用法
。
多个defer
的执行顺序
通常来说,defer
是在程序的最后才执行。当多个defer
出现时,遵循 栈 的先入后出顺序执行。
在这里插入图片描述
defer
与return
一起使用
关于defer
与return
的执行顺序,普遍来说是先return
后defer
,可以参考此例。(直接cv一个,懒得写了)。
go
package main
import "fmt"
func deferFunc() int {
fmt.Println("defer func called")
return 0
}
func returnFunc() int {
fmt.Println("return func called")
return 0
}
func returnAndDefer() int {
defer deferFunc()
return returnFunc()
}
func main() {
returnAndDefer()
}
------------------------------------------------
原文作者:刘丹冰Aceld
转自链接:https://learnku.com/articles/42255
版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请保留以上作者信息和原文链接。
go
执行结果
return func called
defer func called
此篇文章中是分了多点来概述此情况------
"知识点 2: defer 与 return 谁先谁后",
"知识点 3:函数的返回值初始化",
"知识点 4: 有名函数返回值遇见 defer 情况"
但我认为这样理解下来较为复杂,因此参考了此文,从return的角度来理解,将其归纳在一起。
return并不是原子操作,而是分为:赋值、返回 两个步骤。
加上defer,三者的执行时机则是:赋值、defer、return。
不带命名返回值
因此对应来看,对于"不带命名返回值"的情况,即func test() int
这样的情况,由于return的值相当于是编译器自己新建的一个var tmp int
,而defer
中进行赋值操作则不会影响tmp
,因此不影响返回值。
go
package main
import "fmt"
func main() {
t := test()
fmt.Println(t)
}
func test() int { //无名返回
i:=9
defer func() {
i++
fmt.Println("defer1=", i)
}()
defer func() {
i++
fmt.Println("defer2=", i)
}()
return i
}
作者:蓝色记忆
链接:https://juejin.cn/post/7095631673865273352
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
此例中,输出内容是:
go
defer2= 10
defer1= 11
9
可以理解为,系统var tmp int
,这个tmp
是需要返回的值,他是9。但是defer
修改的是i
,所以互不干涉。
有名返回值
对于有名返回值的情况,由于有名,所以没有了var tmp int
这一步,defer中执行的修改会影响return
的值,因此会影响。
defer
配合panic
与recover
参考资源
https://learnku.com/articles/42255
https://juejin.cn/post/7095631673865273352
https://juejin.cn/post/7304183399885996067
defer
与return
一起使用
关于defer
与return
的执行顺序,普遍来说是先return
后defer
,可以参考此例。(直接cv一个,懒得写了)。
go
package main
import "fmt"
func deferFunc() int {
fmt.Println("defer func called")
return 0
}
func returnFunc() int {
fmt.Println("return func called")
return 0
}
func returnAndDefer() int {
defer deferFunc()
return returnFunc()
}
func main() {
returnAndDefer()
}
------------------------------------------------
原文作者:刘丹冰Aceld
转自链接:https://learnku.com/articles/42255
版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请保留以上作者信息和原文链接。
go
执行结果
return func called
defer func called
此篇文章中是分了多点来概述此情况------
"知识点 2: defer 与 return 谁先谁后",
"知识点 3:函数的返回值初始化",
"知识点 4: 有名函数返回值遇见 defer 情况"
但我认为这样理解下来较为复杂,因此参考了此文,从return的角度来理解,将其归纳在一起。
return并不是原子操作,而是分为:赋值、返回 两个步骤。
加上defer,三者的执行时机则是:赋值、defer、return。
不带命名返回值
因此对应来看,对于"不带命名返回值"的情况,即func test() int
这样的情况,由于return的值相当于是编译器自己新建的一个var tmp int
,而defer
中进行赋值操作则不会影响tmp
,因此不影响返回值。
go
package main
import "fmt"
func main() {
t := test()
fmt.Println(t)
}
func test() int { //无名返回
i:=9
defer func() {
i++
fmt.Println("defer1=", i)
}()
defer func() {
i++
fmt.Println("defer2=", i)
}()
return i
}
作者:蓝色记忆
链接:https://juejin.cn/post/7095631673865273352
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
此例中,输出内容是:
go
defer2= 10
defer1= 11
9
可以理解为,系统var tmp int
,这个tmp
是需要返回的值,他是9。但是defer
修改的是i
,所以互不干涉。
有名返回值
对于有名返回值的情况,由于有名,所以没有了var tmp int
这一步,defer中执行的修改会影响return
的值,因此会影响。
defer
配合panic
与recover
参考资源
https://learnku.com/articles/42255
https://juejin.cn/post/7095631673865273352
https://juejin.cn/post/7304183399885996067