defer
Go 语言中的defer
语句会将其后面跟随的语句进行延迟处理。在defer
归属的函数即将返回时,将延迟处理的语句按defer
定义的逆序进行执行,也就是说,先被defer
的语句最后被执行,最后被defer
的语句,最先被执行。
如下:
package main
import "fmt"
func main() {
fmt.Println("start")
defer fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
fmt.Println("end")
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
输出结果如下:
start
end
3
2
1
1
2
3
4
5
2
3
4
5
由于defer
语句延迟调用的特性,所以defer
语句能非常方便的处理资源释放问题。比如:资源清理、文件关闭、解锁及记录时间等。
# defer 执行机
在 Go 语言的函数中return
语句在底层并不是原子操作,它分为给返回值赋值和 RET 指令两步。而defer
语句执行的时机就在返回值赋值操作后,RET 指令执行前。具体如下图所示:
# panic 和 recover
在函数部分介绍了几个内部函数,其中panic
和revocer
是 Go 语言中用来处理错误的。
比如:
package main
import "fmt"
func f1() {
fmt.Println("f1 func...")
}
func f2() {
var status bool
// 关闭数据库
func() {
fmt.Println("关闭数据库失败")
status = false
}()
if !status {
panic("这里出现了严重的错误")
}
fmt.Println("f2 func...")
}
func f3() {
fmt.Println("f3 func...")
}
func main() {
f1()
f2()
f3()
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
执行的结果如下:
f1 func
关闭数据库失败
panic: 这里出现了严重的错误
goroutine 1 [running]:
main.f2()
E:/DEV/Go/src/code.rookieops.com/day02/defer/main.go:14 +0x40
main.main()
E:/DEV/Go/src/code.rookieops.com/day02/defer/main.go:24 +0x85
exit status 2
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
上面的例子程序执行到f2
函数的panic
的时候就触发错误直接退出了,后面的语句和f3
函数没有继续执行。如果要继续执行后面的语句就需要使用recover
函数,如下:
package main
import "fmt"
func f1() {
fmt.Println("f1 func...")
}
func f2() {
var status bool
// 关闭数据库
func() {
fmt.Println("关闭数据库失败")
status = false
}()
// 用revocer()恢复
defer func() {
err := recover()
if err != nil {
fmt.Println("恢复了,继续执行后面语句")
}
}()
if !status {
panic("这里出现了严重的错误")
}
fmt.Println("f2 func...")
}
func f3() {
fmt.Println("f3 func...")
}
func main() {
f1()
f2()
f3()
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
其输出的结果如下:
f1 func...
关闭数据库失败
恢复了,继续执行后面语句
f3 func...
1
2
3
4
2
3
4
注意:
- recover 必须和 defer 搭配使用
- defer 一定 要在可能引发 panic 之前定义
上次更新: 2025/07/18, 18:41:03
← 函数 类型别名与自定义类型→