内容简介:Go里面,流程控制语句中有一个下面用代码说话。
Go里面,流程控制语句中有一个 defer
的关键字,翻译过来就是延迟的意思。
下面用代码说话。
func deferFunc() { defer fmt.Println("后打印") fmt.Println("先打印") }
defer
在函数执行完毕之后,才会执行,所以,我们经常在释放资源或异常处理等需要收尾的场景下会用到 defer
。
不过 defer
也有一些“坑”,大家需要注意一下。
func printNumbers() { for i := 0; i < 5; i++ { defer func() { fmt.Print(i) // 输出55555 }() } }
上面例子中, defer
是在 for
循环全部执行完毕之后才会执行,所以 i
已经变成了 5
,正确做法是下面这样
func printNumbers() { for i := 0; i < 5; i++ { defer func(j int) { fmt.Print(j) // 输出43210 }(i) } }
上面打印的是倒序,这是因为 defer
的执行顺序和栈的特性一样,都是 先进后出
的
defer
还有一个特性,当函数有参数传入时,那些参数的值会在声明时求出
func printNumbers() { for i := 0; i < 5; i++ { defer func(j int) { fmt.Print(j) // 输出86420 }(i * 2) } }
上面的例子大家可能看的不是很清楚,下面给过一个例子
func main() { i := 2 defer fmt.Println(i) // 输出2,原因就是上面说的 i = 8 fmt.Println(i) }
上面这个例子就很明显了,后面 i
如何变都不会影响 defer
输出的内容
defer
还有一个经常在面试中提到的问题,就是和 return
的执行顺序,下面是我整理的3个例子
func main() { fmt.Println("a return: ", a()) fmt.Println("b return: ", b()) fmt.Println("c return: ", *c()) } func a() int { var i int defer func() { i = 1 fmt.Println("a defer i: ", i) }() return i } func b() (i int) { defer func() { i = 2 fmt.Println("b defer i: ", i) }() return i } func c() *int { var i int defer func() { i = 3 fmt.Println("c defer i: ", i) }() return &i } // 输出 a defer i: 1 a return: 0 b defer i: 2 b return: 2 c defer i: 3 c return: 3
原因网上有很多优秀的解释,我就再说一下我的理解
-
a
函数之所以返回0
,是因为返回值是无名的,return
把i
的值写入返回值后,defer
再修改i
的值,但是已经影响不到返回值了 -
b
函数之所以返回1
,是因为返回值已经声明成i
了,return
之后,defer
对i
修改自然就影响了return的返回值了 -
c
函数结果和a
函数不一样,是因为返回值是指针类型,一样的道理,返回值改不了,但是返回值指向的值已经更改,所以就有上面的结果
正常工作里面,虽然不可能写这种代码,但是面试的时候这些基础问题出现的频率还是挺高的,所以大家也是需要掌握一下。融汇贯通,自己多操作多试试,加深印象。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Swift 5.1 新特性:透明类型关键字 some
- 大数据成神之路-Java高级特性增强(volatile关键字)
- 番外篇2-基本规范、注释、static关键字、import关键字
- 说说iOS中的常用的关键字static ,class(仅限Swift关键字)
- Golang 关键字
- 2019 关键字
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。