Golang defer使用

2023-07-29,

学习于https://www.liwenzhou.com/posts/Go/function/的文章

1. defer的执行顺序类似于栈,“后进先出”,也就是最先defer的语句最后执行,而最后defer的最先执行

func main() {
defer fmt.Println("1")
defer fmt.Println("2")
defer fmt.Println("3")
} //控制台打印
3
2
1

2. defer和return的坑

首先return操作并不是原子操作,他分为2步:一是给返回值赋值,二是return返回值。如果函数中有defer的话,那么defer会被夹杂在2步中间,也就是先给返回值赋值,执行defer,return返回值

func main() {
fmt.Println("匿名返回:", a()) //5
fmt.Println("有名返回:", b()) //6
} // 匿名返回值
func a() int {
x := 5
defer func() {
x++
}()
return x
} // 有名返回值
func b() (x int) {
x = 5
defer func() {
x++
}()
return x
}

使用匿名返回函数,控制台打印的是5,这是执行return x时,首先定义 返回值=x(非同一个变量),然后执行defer x++,最后return返回值,而此时返回值已经=x,x++不会再影响返回值了,所以返回的是5。

使用有名返回时,就指定了返回值=x(同一个变量,内存地址相同),所以x++后,返回的值也++了。

3. defer注册要延迟执行的函数时该函数所有的参数都需要确定其值

func calc(index string, a, b int) int {
ret := a + b
fmt.Println(index, a, b, ret)
return ret
} func main() {
x := 1
y := 2
defer calc("AA", x, calc("A", x, y))
x = 10
defer calc("BB", x, calc("B", x, y))
y = 20
}

第一次注册defer calc("AA", x, calc("A", x, y))时,会执行里面的calc("A", x, y),此时x=1,y=2,所以先打印,

A 1 2 3

于是defer calc("AA", x, calc("A", x, y))中的参数被确定,是defer calc("AA", 1, 3)

接下来x=10,y没变,仍等于2,执行defer calc("BB", x, calc("B", x, y)),执行calc("B", x, y),打印

B 10 2 12

于是defer calc("BB", x, calc("B", x, y))中的参数被确定,是defer calc("BB", 10, 12)

然后按照defer顺序执行,先执行defer calc("BB", 10, 12),再执行defer calc("AA", 1, 3),所以打印

BB 10 12 22
AA 1 3 4

Golang defer使用的相关教程结束。

《Golang defer使用.doc》

下载本文的Word格式文档,以方便收藏与打印。