面试题
这是Go Quiz系列的第4篇,关于Go语言的defer
语义。
这道题稍微有点迷惑性,通过这道题可以加深我们对Go语言defer
关键字底层运行机制的理解。
package main type Foo struct { v int } func NewFoo(n *int) Foo { print(*n) return Foo{} } func (Foo) Bar(n *int) { print(*n) } func main() { var x = 1 var p = &x defer NewFoo(p).Bar(p) x = 2 p = new(int) NewFoo(p) }
- A: 100
- B: 102
- C: 022
- D: 011
这道题主要考察以下知识点:
- 被
defer
的函数或方法什么时候执行? - 被
defer
的函数或方法的参数的值是什么时候确定的? - 被
defer
的函数或方法如果存在多级调用是什么机制?比如本题的NewFoo(p).Bar(p)
就存在二级调用,先调用了NewFoo
函数,再调用了Bar
方法。
解析
我们再看看官方文档怎么说的:
Each time a "defer" statement executes, the function value and parameters to
the call are evaluated as usual and saved anew but the actual function is not
invoked.Instead, deferred functions are invoked immediately before the
surrounding function returns, in the reverse order they were deferred.That is, if the surrounding function returns through an explicit return statement,
deferred functions are executed after any result parameters are set by that
return statement but before the function returns to its caller.If a deferred function value evaluates to nil, execution panics when the function is
invoked, not when the "defer" statement is executed.
官方文档的前两句话对我们求解本题至关重要,用中文来表述就是:
假设我们在函数A
的函数体内运行了defer B(params)
,那被defer
的函数B
的参数会像普通函数调用一样被计算,但是被defer
的函数B
的调用会延迟到函数A
return或者