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") }
|
修改函数的具名返回值
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 y = b + 6 return }
func main() { x, y := foo(1, 2) fmt.Println("x=", x, "y=", y) }
|
deferred函数在foo真正将执行权返回给main函数之前,将foo的两个返回值x和y分别放大了5倍和10倍。
输出调试信息
还原变量旧值
关于defer的几个关键问题
明确哪些函数可以作为deferred函数
把握好defer关键字后表达式的求值时机
知晓defer带来的性能损耗