golang defer
这个使用的执行流程一直很绕,所以决定写一篇文记录一下。
规则一:当defer被声明时,其参数就会被实时解析
案例一
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
|
package main
import (
"fmt"
)
func main() {
test()
}
func test() {
defer f1(f2())
fmt.Println("2")
return
}
func f1(i int) int {
return i
}
func f2() int {
fmt.Println("1")
return 1
}
|
输出:12
案例二
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
package main
import (
"fmt"
)
func main() {
defer getFunc()()
fmt.Println("2")
}
func getFunc() func() {
fmt.Println("1")
return func() {
fmt.Println("3")
}
}
|
输出:123
注意区分传入的是函数变量还是函数
1、函数变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
package main
import (
"fmt"
)
func main() {
defer f3(f2)
fmt.Println("2")
}
func f2() int {
fmt.Println("1")
return 1
}
func f3(f func() int) int {
return f()
}
|
输出:21
2、函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
package main
import (
"fmt"
)
func main() {
defer f1(f2())
fmt.Println("2")
}
func f1(i int) int {
return i
}
func f2() int {
fmt.Println("1")
return 1
}
|
输出:12
规则二:defer执行顺序为先进后出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
package main
import (
"fmt"
)
func main() {
defer func() {
fmt.Println("3")
}()
defer func() {
fmt.Println("2")
}()
fmt.Println("1")
}
|
输出:123
规则三:defer可以读取有名返回值
1
2
3
4
5
6
7
8
|
func main() {
i := 1
defer func() {
i++
fmt.Println(i)
}()
fmt.Println(i)
}
|
输出:12
所有规则复合体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
package main
import (
"fmt"
)
type msg struct {
Num int
}
func (m *msg) print() {
fmt.Println(m.Num)
}
func main() {
m := new(msg) // 注意 new 返回一个指针
m.Num = 1
defer m.print()
defer func(m msg) {
m.print()
}(*m)
m.Num = 2
}
|
输出:12
可用于异常捕获
golang中 defer,panic,recover 是很常用的三个特性,三者一起使用可以充当其他语言中 try…catch… 的角色,而defer本身又像其他语言的析构函数。
可以在具体实现层 defer,panic,recover 也可以同时在最外层再 defer,panic,recover。异常捕获,按栈式,后入先出,一次性捕获,具体实现层捕获后,外层就不会再次捕获的。
panic其实就是c++中的throw exception
recover也是一个内建函数. recover就是c++中的catch.
- recover如果想起作用的话, 必须在defered函数中使用.
- 在正常函数执行过程中, 调用recover没有任何作用, 他会返回nil. 如这样:fmt.Println(recover()) // 输出 nil
- 如果当前的goroutine panic了, 那么recover将会捕获这个panic的值, 并且让程序正常执行下去, 不会让程序crash.
1
2
3
4
5
6
|
defer func() {
if r := recover(); r !=nil {
logger.Sugar.Error(r)
fmt.Println("Recovered in f", r)
}
}
|
转载声明
作者:DukeAnn
链接:https://learnku.com/articles/43494#reply138836
来源:LearnKu
著作权归作者所有,任何形式的转载都请联系作者