【翻译】【Go】了解Defer、Panic、Recover
yankewei · · 1088 次点击 · · 开始浏览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.
复制代码参考资料:
有疑问加站长微信联系(非本文作者)
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
关注微信- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码` - 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传
收入到我管理的专栏 新建专栏
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.
复制代码参考资料: