使用defer关键字的函数返回类型带参数名的时候,返回结果会受影响的原因是什么
来源:2-6 函数

JToGo
2020-02-07
老师:
你好!
今天做面试题的时候发现,函数返回类型带参数名的时候,如果使用的defer关键字,是会影响到最终返回值的。能否讲解一下原理?
比如下面的两段代码:
func DeferFunc1(i int) (t int) {
t = i
defer func() {
t += 3
}()
return t
}//这一段代码最终返回结果是3+t
func DeferFunc2(i int) int {
t := i
defer func() {
t += 3
}()
return t
}//这一段的返回结果是t
1回答
-
题外话,这么快就出了这种没啥实际作用扣语言细节的题,我不赞成这样的面试题。
回到题目本身,这里返回多少不是人为设计的,而是编译器实现defer,以及命名返回值(t int)后自然的做法。defer函数的执行应该是在return语句之后。
这里有两个关键点:
defer的时机是在return之后。
命名返回值,就是DeferFunc1里的t,它的生命周期比函数体要大,函数一开始返回的仍然是i,但是这个返回值被defer修改了。我们建议在使用命名返回值的时候,return后面不要带值。这样的写法其实是不可取的,故意误导。
我根据原理等价改写了一下代码:
DeferFunc2中,返回值没有命名,所以编译器分配了个返回值res,用来接返回值。随后的t+=3不影响res。
func DeferFunc2(i int) int {
var t int
res := func() int {
t = i
return t
}()
func() {
t += 3
}()
return res
}DeferFunc1中,由于命名了返回值为t,就不需要分配变量res,return t实际上是把t的值赋值为return后面的值,后面t+=3就影响了返回值。
func DeferFunc1(i int) (t int) {
t = func() int {
t = i
return t
}()
func() {
t += 3
}()
return t
}112020-02-29
相似问题