golang 的异常处理(Panic和Recover)
Panic和Recover
Go没有像Java那样的异常机制,它不能抛出异常,而是使用了panic
和recover
机制。一定要记住,你应当把它作为最后的手段来使用,也就是说,你的代码中应当没有,或者很少有panic
的东西。这是个强大的工具,请明智地使用它。那么,我们应该如何使用它呢?
Panic
是一个内建函数,可以中断原有的控制流程,进入一个令人恐慌的流程中。当函数F
调用panic
,函数F
的执行被中断,但是F
中的延迟函数会正常执行,然后F
返回到调用它的地方。在调用的地方,F
的行为就像调用了panic
。这一过程继续向上,直到发生panic
的goroutine
中所有调用的函数返回,此时程序退出。恐慌可以直接调用panic
产生。也可以由运行时错误产生,例如访问越界的数组。
Recover
是一个内建的函数,可以让进入令人恐慌的流程中的goroutine
恢复过来。recover
仅在延迟函数中有效。在正常的执行过程中,调用recover
会返回nil
,并且没有其它任何效果。如果当前的goroutine
陷入恐慌,调用recover
可以捕获到panic
的输入值,并且恢复正常的执行。
下面这个函数演示了如何在过程中使用panic
var user = os.Getenv("USER") func init() { if user == "" { panic("no value for $USER") } }
下面这个函数检查作为其参数的函数在执行时是否会产生panic
:
func throwsPanic(f func()) (b bool) { defer func() { if x := recover(); x != nil { b = true } }() f() //执行函数f,如果f中出现了panic,那么就可以恢复回来 return }
最容易理解就是给个例子,文章里有例子:
package main import ( "fmt" //"os" ) var user = "" func inita() { defer func() { fmt.Print("defer##\n") }() if user == "" { fmt.Print("@@@before panic\n") panic("no value for user\n") fmt.Print("!!after panic\n") } } func throwsPanic(f func()) (b bool) { defer func() { if x := recover(); x != nil { fmt.Print(x) b = true } }() f() fmt.Print("after the func run") return } func main() { throwsPanic(inita) }
执行结果:
D:\go>go run b.go
@@@before panic
defer##
no value for user
如上面所说的:
panic
在user=""
时,打断了函数的执行,fmt.Print("!!after panic\n")
没有执行。 但函数中的延迟函数会正常执行,打印了 defer##
。然后返回到调用该函数的地方,继续上面的过程。
直到执行完所有函数的defer
,退出程序。Recover
可以捕获到panic
的值,上面的打印no value for user
。并且恢复正常的执行。
转自:http://www.blogjava.net/oathleo/archive/2013/09/22/404272.html