- recover能够有效捕获panic的范围:
- 在Go语言中,
recover
只有在defer
函数中调用才能捕获到panic
。并且这个defer
函数必须与引发panic
的代码在同一函数调用栈层级,或者是在从引发panic
的函数直接或间接调用的函数中的defer
函数里。
- 例如:
package main
import "fmt"
func main() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered in main:", r)
}
}()
callFunction()
}
func callFunction() {
panic("Some panic in callFunction")
}
- 在上述代码中,
main
函数中的defer
函数能够捕获到callFunction
函数中引发的panic
,因为callFunction
是从main
函数直接调用的。
- 在错误的作用域使用recover可能出现的情况:
- 如果
recover
不在defer
函数中调用,它将始终返回nil
,无法捕获到panic
。例如:
package main
import "fmt"
func main() {
if r := recover(); r != nil {
fmt.Println("Recovered in main:", r)
}
callFunction()
}
func callFunction() {
panic("Some panic in callFunction")
}
- 这段代码中,
recover
不在defer
函数内,所以它永远不会捕获到panic
,程序会因为未捕获的panic
而崩溃。
- 另外,如果
recover
在与引发panic
不在同一调用栈层级的defer
函数中(没有直接或间接调用关系),也无法捕获到panic
。例如:
package main
import "fmt"
func main() {
go func() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered in goroutine:", r)
}
}()
callFunction()
}()
fmt.Println("Main continues")
select {}
}
func callFunction() {
panic("Some panic in callFunction")
}
- 在这个例子中,
callFunction
在一个新的goroutine中调用,main
函数中的defer
函数无法捕获到该goroutine中的panic
,因为它们不在同一调用栈层级。新的goroutine会因为未捕获的panic
而崩溃,而main
函数会继续运行(这里通过select {}
防止main
函数提前退出)。