MST
星途 面试题库

面试题:Go语言中recover使用限制之作用域相关

在Go语言中,recover用于捕获panic异常。请简述在不同的函数调用层级和作用域中,recover能够有效捕获panic的范围是怎样的?举例说明如果在错误的作用域使用recover可能会出现什么情况。
17.1万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
  1. 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函数直接调用的。
  1. 在错误的作用域使用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函数提前退出)。