1.defer的执行顺序
底层是采用栈
func func1() {
fmt.Println("A")
}
func func2() {
fmt.Println("B")
}
func func3() {
fmt.Println("C")
}
func main() {
defer func1()
defer func2()
defer func3()
}
输出 C B A
2.defer和return 的顺序
在Go语言的函数中return
语句在底层并不是原子操作,它分为给返回值赋值和RET指令两步。而defer
语句执行的时机就在返回值赋值操作后,RET指令执行前。具体如下图所示:
一 .
func f1() int {
x := 5
defer func() {
x++
}()
return x
}
输出 5
f1()函数没有命名返回值。
- 返回值开辟了一块新的内存空间0x aaaaa某某,未命名。赋值为5
- 运行defer x=6 ,这里x跟返回值已经没有关系了
- ruturn 是指向0x aaaaa 这片区域的值
二.
func f1() (x int) {
defer func() {
x++
}()
return 5
}
输出 6
f1()函数命名返回值x。
-
返回值开辟了一块新的内存空间0x aaaaa,赋值为x=5
-
运行defer x=6 。同时修改了指向0x aaaaa的值
-
return 指向0x aaaaa区域的值
三.
func f1() (y int) {
x := 5
defer func() {
x++
}()
return x
}
输出 5
f1()函数命名返回值y。
-
返回值开辟了一块新的内存空间0x aaaaa,赋值为y=5
-
运行defer x=6 。
-
return 指向0x aaaaa区域的值
四 .
func f1() (x int) {
defer func(x int ) {
x++
}(x)
return 5
}
输出 5
f1()函数命名返回值x。
-
返回值开辟了一块新的内存空间0x aaaaa,赋值为x=5
-
运行defer , 通过参数传入。这里参数是新开辟的地址, 修改不了0x aaaaa下的x值
-
return 指向0x aaaaa区域的值