在本教程中,您将了解Go语言中的恢复(recover)和恐慌(panic)。在开始本教程之前,请确保您了解我们在上一个教程中讨论过的panic概念。
recover函数是Go编程语言中用于从panic情况中恢复的内置函数。因此,即使Go程序中发生panic,它也能够从该panic中恢复并继续正常执行。这就是recover关键字的意义所在。
让我们通过下面的panic程序开始学习
package main
import "fmt"
func main() {
fmt.Println("lets learn about recover() in golang")
Panicfunc()
fmt.Println("learned all about recover() ")
}
func Panicfunc() {
fmt.Println("instruction just before panicking situation")
panic("Panicfunc terminates from execution")
fmt.Println("instruction after panic does not execute")
}
输出
lets learn about recover() in golang instruction just before paniciking situation panic: Panicfunc terminates from execution goroutine 1 [running]: main.Panicfunc() /tmp/sandbox1636989584/prog.go:13 +0x65 main.main() /tmp/sandbox1636989584/prog.go:7 +0x5b Program exited.
一个panic函数是Go语言中的一个异常,程序会终止其正常执行,因为它不知道接下来该做什么,并留下一个错误消息,这个消息要么是程序员使用内置的panic函数作为参数传入的,要么是运行时默认生成的。
给定的程序由两个函数组成,一个是main(),另一个是Panicfunc()。
当程序从主函数开始执行时,它会执行第一条指令以打印“让我们了解Go语言中的recover()”。
fmt.Println("让我们了解Go语言中的recover()")
主函数扫描下一条要执行的指令,这是一个名为Panicfunc()的函数。控制权切换到Panicfunc(),在那里执行一组指令。下面给出的第一条指令被执行并打印
在发生panic情况之前的指令。
fmt.Println("在panic情况之前的指令")
panic("Panicfunc终止执行")
当程序遇到panic函数时,它会终止执行下面的指令,并打印该字符串,即panic: Panicfunc终止执行,并留下一些堆栈跟踪。
让我们继续使用上面讨论的相同代码,但添加了一些新代码。
在上面的代码中添加了一个名为Panicrecover的新函数,其中使用了预定义的recover()函数。
func Panicrecover() {
if err := recover(); err != nil {
fmt.Println("Recovered from panic \n", err)
}
为了恢复正常的执行流程,我们需要在Panicfunc ()中添加defer函数。
要理解defer的意义,请参考我们已经介绍过的教程。Recover在延迟函数中很有用。因此,如果您想在panic函数中(即在我们的示例Panicfunc中)使用Panicrecover函数(recover ()),您需要调用defer函数,它表示
defer Panicrecover()
让我们回顾一下defer的概念。
任何被延迟调用的函数都称为延迟函数,它们在封闭函数之前被调用。在我们的程序中,上面给出的代码将延迟recover函数。
在这个程序中,当发生panic时,Panicfunc通过调用Panicrecover函数来恢复。在Panicrecover函数内部,我们调用了内置的recover(),它允许程序正常执行。执行从main()调用的Panicfunc()函数处恢复。
让我们检查完整的代码
package main
import "fmt"
func main() {
fmt.Println("lets learn about recover() in golang")
Panicfunc()
fmt.Println("learned all about recover() ")
}
func Panicfunc() {
defer Panicrecover()
fmt.Println("instruction just before panicking situation")
panic("Panicfunc resume execution")
fmt.Println("instruction after panic does not execute")
}
func Panicrecover() {
if err := recover(); err != nil {
fmt.Println("Recovered from panic \n", err)
}
}
输出
lets learn about recover() in golang instruction just before panicking situation Recovered from panic Panicfunc resume execution learned all about recover() Program exited.
程序中的控制流

让我们总结一下上面给出的流程图
是的,recover函数在正常执行期间返回nil值。
考虑上面讨论的相同代码,但省略了panic情况。只需删除
panic("Panicfunc resume execution")
代码如下所示
package main
import "fmt"
func main() {
fmt.Println("lets learn about recover() in golang")
Panicfunc()
fmt.Println("learned all about recover() ")
}
func Panicfunc() {
defer Panicrecover()
fmt.Println("instruction just before panicking situation")
fmt.Println("instruction after panic does not execute")
}
func Panicrecover() {
if err := recover(); err != nil {
fmt.Println("Recovered from panic \n", err)
}
}
输出
lets learn about recover() in golang instruction just before panicking situation instruction after panic does not execute learned all about recover() Program exited.
在上面的程序中,控制流正常。recover函数没有什么可恢复的,没有panic情况,所以它返回一个nil值。
更好地理解下面带有recover函数(包含else部分,说明recover函数返回nil值)的程序。
package main
import "fmt"
func main() {
fmt.Println("lets learn about recover() in golang")
Panicfunc()
fmt.Println("learned all about recover() ")
}
func Panicfunc() {
defer Panicrecover()
fmt.Println("instruction just before paniciking situation")
fmt.Println("instruction after panic does not execute")
}
func Panicrecover() {
if err := recover(); err != nil {
fmt.Println("Recovered from panic \n", err)
} else {
fmt.Println("Recover a nil value :", err)
}
}
输出
lets learn about recover() in golang instruction just before paniciking situation instruction after panic does not execute Recover a nil value :learned all about recover() Program exited.
注意