我们知道 defer 的时候会将后面的函数入栈,然后 return 的时候执行。
那么具体是什么样子的呢。
分 4 步:
- 遇到defer函数,计算defer函数的参数值,入栈
- 将return后面的值计算出来,赋给t(这个t是函数声明中要返回的的变量)
- 执行defer函数
- 空的return(结果就是那个t)
关于 defer 函数的参数什么时候计算
package main
import (
"fmt"
"time"
)
func main() {
defer fmt.Println(time.Now()) // 1
time.Sleep(time.Second)
fmt.Println(time.Now()) // 3
}
先 print 的时间(line 3)是要比后 print 的时间(line 1)多 1s 的,所以是先计算 defer 的参数,入栈,然后再继续往下执行
关于 return 后面的参数与 defer 函数之间的关系
最重要的一点就是要明白,return xxx 这一条语句并不是一条原子指令!
下面这段代码给了三个使用了 defer 的函数f_x()
,然后将其分解开了,写成了g_x()
,希望通过这个分解让你对 defer 更加了解。
package main
import "sync"
func f1() (result int) {
defer func() {
result++
}()
return 0
}
func g1() (result int) {
result = 0 // 1
result++ // 2
return // 3
}
func f2() (r int) {
t := 5
defer func() {
t = t + 5
}()
return t
}
func g2() (r int) {
t := 5
r = t // 1
t = t + 5 // 2
return // 3
}
func f3() (r int) {
defer func(r int) {
r = r + 5
}(r)
return 1
}
func g3() (r int) {
r = 1 // 1
var s = sync.WaitGroup{} // 2
s.Add(1) // 2
go func(r int) { r = r + 5; s.Done() }(r) // 2
s.Wait() // 2
return // 3
}
func main() {
println(f1(), f1() == g1())
println(f2(), f2() == g2())
println(f3(), f3() == g3())
}
结果是
1 true
5 true
1 true