File tree Expand file tree Collapse file tree 1 file changed +66
-0
lines changed Expand file tree Collapse file tree 1 file changed +66
-0
lines changed Original file line number Diff line number Diff line change
1
+ /*
2
+ defer func (){
3
+ // 执行复杂的清理工作 ...
4
+ }
5
+
6
+ 另外,一个函数/方法中可以存在多个 defer 语句,defer 语句的调用顺序遵循先进后出的原则,即最后一个 defer 语句将最先被执行,
7
+ 相当于「栈」结构,如果在循环语句中包含了 defer 语句,则对应的 defer 语句执行顺序依然符合先进后出的规则。
8
+ 由于 defer 语句的执行时机和调用顺序,所以我们要尽量在函数/方法的前面定义它们,以免在后面执行时漏掉,尤其是运行时抛出错误会中断后面代码的执行,
9
+ 也就感知不到后面的 defer 语句。
10
+ 下面我们看一个简单的示例 defer.go:
11
+ */
12
+
13
+ package main
14
+
15
+
16
+ import (
17
+ "fmt"
18
+ )
19
+
20
+ func printError (){
21
+ fmt .Println ("娄底执行" )
22
+ }
23
+
24
+ func main (){
25
+
26
+ // 栈结构,先进后出
27
+ defer printError ()
28
+ defer func (){
29
+ fmt .Println ("除数不能为0!" )
30
+ }()
31
+
32
+ var i = 1
33
+ var j = 0
34
+ var k = i / j
35
+ fmt .Printf ("%d / %d = %d\n " ,i ,j ,k )
36
+ }
37
+
38
+ /*
39
+ 这段代码中,我们定义了两个 defer 语句,并且是在函数最顶部,以确保异常情况下也能执行。
40
+
41
+ 在函数正常执行的情况下,这两个 defer 语句会在最后一条打印语句执行完成后先执行第二条 defer 语句,再执行第一条 defer 语句
42
+
43
+ 1 / 1 = 1
44
+ 除数不能为0!
45
+ 娄底执行
46
+
47
+ 而如果我们把 j 的值设置为 0,则函数会抛出 panic:
48
+ ====================================================
49
+ 除数不能为0!
50
+ 娄底执行
51
+ panic: runtime error: integer divide by zero
52
+
53
+ goroutine 1 [running]:
54
+ main.main()
55
+ D:/goLang/github/golang_project/错误和异常处理/defer 语句及使用示例/defer.go:34 +0x58
56
+ exit status 2
57
+ ===================================================
58
+
59
+ 表示除数不能为零,这个时候,也会执行 defer 语句,底层的逻辑是在执行 var k = i / j 这条语句时,遇到除数为0,
60
+ 则抛出异常 panic,然后立即中断当前函数 main 的执行(后续语句都不再执行),
61
+ 并按照先进后出顺序依次执行定义在当前函数中的 defer 语句,最后打印出 panic 日志及错误信息。
62
+ 关于 panic 及其内部执行逻辑,学院君将在下一篇教程给大家介绍。
63
+
64
+ 总结一下,Go 语言的 defer 语句相当于 PHP 中析构函数和 finally 语句的功效,
65
+ 常用于定义兜底逻辑,在函数执行完毕后或者运行抛出 panic 时执行,如果一个函数定义了多个 defer 语句,则按照先进后出的顺序执行。
66
+ */
You can’t perform that action at this time.
0 commit comments