不会飞的章鱼

熟能生巧,勤能补拙;念念不忘,必有回响。

Go语言精进——使用defer让函数更简洁、更健壮

defer的运作机制

  • 在 Go 中,只有在函数(和方法)内部才能使用 defer;
  • defer 关键字后面只能接函数(或方法),这些函数被称为deferred 函数。defer 将它们注册到其所在 Goroutine 中,用于存放 deferred 函数的栈数据结构中,这些deferred 函数将在执行 defer 的函数退出前,按后进先出(LIFO)的顺序被程序调度执行:

defer的常见用法

拦截panic

按需要对panic进行处理,可以尝试从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
func bar() {
fmt.Println("raise a panic")
panic(-1)
}

func foo() {
defer func() {
if e := recover(); e != nil {
fmt.Println("recovered from a panic")
}
}()
bar()
}

func main() {
foo()
fmt.Println("main exit normally")
}

/*
raise a panic
recovered from a panic
main exit normally
*/

修改函数的具名返回值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func foo(a, b int) (x, y int) {
defer func() {
x = x * 5
y = y * 10
}()

x = a + 5 // 6
y = b + 6 // 8
return
}

func main() {
x, y := foo(1, 2)
fmt.Println("x=", x, "y=", y) // x= 30 y= 80
}

deferred函数在foo真正将执行权返回给main函数之前,将foo的两个返回值x和y分别放大了5倍和10倍。

输出调试信息

还原变量旧值

关于defer的几个关键问题

明确哪些函数可以作为deferred函数

把握好defer关键字后表达式的求值时机

知晓defer带来的性能损耗

------ 本文结束------
如果本篇文章对你有帮助,可以给作者加个鸡腿~(*^__^*),感谢鼓励与支持!