defer综合

A "defer" statement invokes a function whose execution is deferred to the moment the surrounding function returns, either because the surrounding function executed a return statement, reached the end of its function body, or because the corresponding goroutine is panicking.

defer语句会在以下几种情况下被执行:
a. 函数执行return语句
b. 执行到函数体结尾
c. goroutine panic之前
 

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. 

每次执行defer语句时,会将其定义的函数和参数保存在一个栈中,但是定义的函数并不会被执行。但是,在外层函数退出之前,defer函数会按照定义的顺序逆序执行。如果外层函数通过显示return语句返回,则defer定义的函数是在设置结果参数之后,返回调用方之前执行。如果defer要执行的函数为nil,则会在定义的函数调用时产生panic,而不是defer语句执行时。

 

1. defer原理分析

a. 多个defer执行顺序

当一个函数中存在多个defer语句时,函数返回之前会按照defer定义的顺序逆序执行,也就是说最先注册的defer函数最后执行。

 

b. defer语句执行时拷贝时机

当defer语句执行时,会将当前时刻的函数值和函数参数进行注册。注册完成之后再次修改函数值和函数参数将不会生效。

 

c. return & defer

return x :返回值 = x   +   RET指令

defer 原理 :返回值 = x + defer语句 + RET指令

 

d. defer & 闭包

func main() {
  x := 1
  defer func() {
    fmt.Println(x)      // 2
  }()
  x++
}

上例中的 func()是一个闭包,闭包的变量本质是对上层变量的引用。

type Closure struct {

  F func()

  x *int

}

 

相比于直接调用函数,延迟调用需要花费更大的代价。这其中包括注册、调用等操作,还有额外的缓存开销。

对于性能要求高且压力大的算法,应该尽量避免延迟调用。

 

posted @ 2020-07-13 23:40  卷毛狒狒  阅读(110)  评论(0编辑  收藏  举报