defer和return

mac2024-04-03  38

多个defer的执行顺序为“后进先出”

defer、return、返回值的执行逻辑:

return最先执行,return负责将结果写入返回值中;接着defer开始执行一些收尾工作;最后函数携带当前返回值退出

代码验证

package main import "fmt" func main() { fmt.Println("func1 return: ", func1()) //1000 fmt.Println("func2 return: ", func2()) //1002 fmt.Println("func3 return: ", *(func3())) //2 } func func1() int { var i int defer func() { i++ fmt.Println("func1 defer1: ", i) }() defer func() { i++ fmt.Println("func1 defer2: ", i) }() i = 1000 return i } func func2() (i int) { defer func() { i++ fmt.Println("func2 defer1: ", i) }() defer func() { i++ fmt.Println("func2 defer2: ", i) }() i = 1000 return i } func func3() *int { var i int defer func() { i++ fmt.Println("func3 defer1:", i) // 打印结果为 func3 defer1: 2 }() defer func() { i++ fmt.Println("func3 defer2:", i) // 打印结果为 func3 defer2: 1 }() return &i }

输出如下:

func1 defer2: 1001 func1 defer1: 1002 func1 result: 1000 func2 defer2: 1001 func2 defer1: 1002 func2 result: 1002 func3 defer2: 1 func3 defer1: 2 func3 result: 2

分析

return会将返回值先保存起来,对于无名返回值来说,保存在一个临时对象中,defer是看不到这个临时对象的;而对于有名返回值来说,就保存在已命名的变量中.

func1()int 函数的返回值没有被提前声名,其值来自于其他变量的赋值,而defer中修改的也是其他变量,而非返回值本身,因此函数退出时返回值并没有被改变。

func2()(i int)函数的返回值被提前声名,也就意味着defer中是可以调用到真实返回值的,因此defer在return赋值返回值 i 之后,再一次地修改了 i 的值,最终函数退出后的返回值才会是defer修改过的值。

func3()*int 的返回值没有被提前声明,但是由于 c()*int 的返回值是指针变量,那么在return将变量 i 的地址赋给返回值后,defer再次修改了 i 在内存中的实际值,因此函数退出时返回值虽然依旧是原来的指针地址,但是其指向的内存实际值已经被成功修改了。

最新回复(0)