我们知道 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

参考