【Go】了解Defer、Panic、Recover
2010 年 10 月 10 日
Go
有流程控制的机制: if
、 for
、 switch
、 goto
。这里我们讨论并不常见的: defer
、 panic
、 recover
。
一个 defer语句
会把一个函数压入一个栈中,当外层函数返回时,会按照后进先出的顺序执行压入的函数。 defer
有三个简单的规则:
-
当defer语句执行的时候,函数的参数也被指定。
在这个例子中,当Println被延迟执行的时候变量i
的值已经被赋值,所以会打印0
而不是1
:
func a() { i := 0 defer fmt.Println(i) i++ return } 复制代码
-
被defer的函数在外层函数返回后遵循后进先出的规则依次被调用。
这个例子将返回3210
:
func b() { for i := 0; i < 4; i++ { defer fmt.Print(i) } } 复制代码
3.被defer的函数可以对外层函数的返回值读取并且赋值,计算。
这个例子将返回2:
func c() (i int) { defer func() { i++ }() return 1 } 复制代码
Panic是一个内置函数,可以停止正常的流程,然后开始_panicking_。当函数 F
调用panic, F
停止,然后 F
内的被 deffer
的函数将被执行,然后 F
返回给调用者。对于调用者来说, F
调用了 panic
。然后继续往上层函数返回,直到当前的 goroutine
返回。 Recover
是一个内置函数,可以捕获到 panic
,Recover只在defer函数中有用。正常的逻辑,recover返回nil,如果当前的goroutine异常,recover将获取panic的值,然后执行逻辑,不会使进程down掉。
这个例子演示了panic和defer的机制:
package main import "fmt" func main() { f() fmt.Println("Returned normally from f.") } func f() { defer fun() { if err := recover(); err != nil { fmt.Prinfln("Recovered in f", r) } }() fmt.Println("Calling g.") g(0) fmt.Println("Returned normally from g.") } func g(i int) { if i > 3 { fmt.Println("Panicking!") panic(fmt.Sprintf("%v"m i)) } defer fmt.Println("Defer in g", i) fmt.Println("Printing in g", i) g(i + 1) } 复制代码
这个程序将输出:
Calling g. Printing in g 0 Printing in g 1 Printing in g 2 Printing in g 3 Panicking! Defer in g 3 Defer in g 2 Defer in g 1 Defer in g 0 Recovered in f 4 Returned normally from f. 复制代码
参考资料: