Golang defer的运行时机和遇到的坑

马谦马谦马谦 2017年11月29日22:03:44 发表评论
文章最后编辑于:2017-11-29 22:09:17

一、defer概述

defergolang中独有的流程控制语句,用于延迟指定语句的运行时机,只能运行于函数的内部,且当他所属函数运行完之后它才会被调用。例如:

它会先打印出HelloWorld,然后再打印出HelloDefer

一个函数中如果有多个defer,运行顺序和函数中的调用顺序相反,因为它们都是被写在了栈中:

运行结果:

二、defer和return

在包含有return语句的函数中,defer的运行顺序位于return之后,但是defer所运行的代码片段会生效:

运行结果:

这里很明显就能看到defer是在return之后运行的!但是有一个问题是defer里执行了语句i +=1,按照这个逻辑的话返回的i值应该是2而不是1。这个问题是由于return的运行机制导致的:return在返回一个对象时,如果返回类型不是指针或者引用类型,那么return返回的就不会是这个对象本身,而是这个对象的副本。

我们可以验证这一个观点:

程序的输出为:

如果把函数的返回值改成指针类型,这时候的main函数中的返回值就会和函数体内的一致:

结果:

三、defer和panic

panic会在defer运行完之后才把恐慌扩散到其他函数:

结果:

四、defer和for循环

不要在defer内使用外部变量,可能会造成一些意想不到的错误:

它的输出的结果是55555,原理很简单,因为defer会在for循环运行完后才会调用,for循环运行完时i的值为5,所以打印的i值会是55555

但是如果循环内的延时函数有参数传入,参数就会在当前defer语句执行的时候求出:

此时就会打印出43210而不是55555了。

 

本文共执行41次查询,耗时0.298秒!
历史上的今天
十一月
29
马谦马谦马谦

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: