Go语言中的defer语句会将其后面跟随的语句进行延迟处理。在defer归属的函数即将返回时,将延迟处理的语句按defer定义的逆序进行执行,也就是说,先被defer的语句最后被执行,最后被defer的语句,最先被执行。defer 语句可以非常方便的处理资源释放问题。
1、example01
defer执行顺序为先进后出,符合栈的结构,可以理解为,在定义defer后依次将对应函数压入栈,在函数结束前,依次出栈执行。
package main
import (
"fmt"
)
func f1() {
fmt.Println("我是f1")
}
func f2() {
fmt.Println("我是f2")
}
func f3() {
fmt.Println("我是f3")
}
func main() {
x := 10
fmt.Println("我是开始!")
defer f1()
defer f2()
defer f3()
x = 20
fmt.Println("x的值是:", x)
fmt.Println("我是结束")
}
//执行结果为:
/*
我是开始!
x的值是: 20
我是结束
我是f3
我是f2
我是f1
*/
2、example02
当defer被声明时,其参数就是明确了的。
package main
import (
"fmt"
)
func f1(x int) int {
fmt.Println("我是f1函数")
return x + 1
}
func f2(x int) int {
fmt.Println("我是f2函数")
return x + 2
}
func f3(x int) int {
fmt.Println("我是f3函数")
return x + 3
}
func f4(x int) int {
fmt.Println("我是f4函数")
return x + 4
}
func f5(x int) int {
fmt.Println("我是f5函数")
return x + 5
}
func main() {
x := 10
fmt.Println("我是开始!")
defer f1(x)
defer f2(x)
defer f3(x)
defer fmt.Println(f4(x))
x = 20
defer fmt.Println(f5(x))
fmt.Println("x的值是:", x)
fmt.Println("我是结束")
}
//输出结果
/**
我是开始!
我是f4函数
我是f5函数
x的值是: 20
我是结束
25
14
我是f3函数
我是f2函数
我是f1函数
**/
3、example03
defer 可以读取有名返回值
在Go语言的函数中return语句在底层并不是原子操作,它分为给返回值赋值和RET指令两步。而defer语句执行的时机就在返回值赋值操作后,RET指令执行前。具体如下图所示:
package main
import (
"fmt"
)
func fn() (x int) {
defer func() {
x++
}()
return 5
}
func main() {
fmt.Println(fn())
}
//运行结果
/**
6
**/
4、defer深入理解练习题(动起手来)
以下例题取自【李文周的博客】
- 例题1
package main
import "fmt"
func f1() int {
x := 5
defer func() {
x++
}()
return x
}
func f2() (x int) {
defer func() {
x++
}()
return 5
}
func f3() (y int) {
x := 5
defer func() {
x++
}()
return x
}
func f4() (x int) {
defer func(x int) {
x++
}(x)
return 5
}
func main() {
fmt.Println(f1())
fmt.Println(f2())
fmt.Println(f3())
fmt.Println(f4())
}
- 例题2
package main
import "fmt"
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
}