Defer Panic Recovery

Defer 在函数返回之前执行

等同于 Java和C# 的 finally

常使用在记的关闭你打开的资源, 比如文件,锁,错误处理等。

如果不用defer, 而是简单的把关闭动作放到逻辑后面,如果执行逻辑时出错退出,关闭就被跳过了。

Panic 和 Recover

Panic主动使当前线程 crash, Recover函数从panic或错误场景中恢复

解释使用方法的 Example

1
2
3
4
5
6
7
8
9
	defer func() {
		fmt.Println("defer func is called") 
		if err := recover(); err != nil {
			fmt.Println(err)
		}
	}()
	panic("a panic is triggered")
// defer func is called
// a panic is triggered

实际使用的example

如果 doSomething() 里panic, defer 的函数会执行,包括recovery 的部分,因为mainI()里的panic

 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
func main() {
    defer func() {
        // 因为有panic,recover() 会得到非nil
        if r := recover(); r != nil {
            fmt.Println("Recovered from", r)
        }

        fmt.Println("Cleaning up...")
    }()

    fmt.Println("Performing some tasks...")
    // 因为 err != nil, main()里的panic 执行,
    if err := doSomething(); err != nil {
        panic(err)
    }
    // 上面的panic 会跳过下面"All tasks completed successfully." 直接defer
    fmt.Println("All tasks completed successfully.")
}
// 被调用的函数panic产生的crush会跳过return nil. 回到main()
func doSomething() error {
    fmt.Println("Doing something...")

    // 模拟一个异常
    panic("Something went wrong!")

    return nil
}
// Performing some tasks...
// Doing something...
// Recovered from Something went wrong!
// Cleaning up...

如果 doSomething() 里不会panic,defer依然会执行。但是"Recovered from"会被跳过

1
2
3
4
// Performing some tasks...
// Doing something...
// All tasks completed successfully.
// Cleaning up...