MST

星途 面试题库

面试题:Go语言中panic和defer以及recover的交互关系

在Go语言里,defer语句与panic、recover之间存在怎样的交互关系?请详细阐述,并通过代码示例展示当多个defer同时存在且其中包含recover时,程序的执行流程和结果。
41.9万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
  1. defer、panic、recover的交互关系

    • defer:defer语句用于延迟函数的执行,在包含defer语句的函数即将返回时,会按照defer语句出现的逆序依次执行这些延迟的函数。
    • panic:panic用于抛出异常,使程序进入恐慌状态,会停止当前函数的正常执行,并开始展开调用栈。在展开调用栈的过程中,会执行该函数中已定义的defer语句。
    • recover:recover只能在defer函数中使用,用于捕获panic抛出的异常,使程序从恐慌状态恢复正常执行。如果在defer函数之外调用recover,将返回nil
  2. 代码示例及执行流程

package main

import (
    "fmt"
)

func main() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered in main:", r)
        }
    }()

    fmt.Println("Before calling f")
    f()
    fmt.Println("After calling f")
}

func f() {
    defer func() {
        fmt.Println("First defer in f")
    }()

    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered in f:", r)
        }
    }()

    defer func() {
        fmt.Println("Second defer in f")
    }()

    fmt.Println("Before panic in f")
    panic("Panic in f")
    fmt.Println("After panic in f")
}
  • 执行流程
    • main函数中,首先打印Before calling f
    • 调用f函数,f函数中首先打印Before panic in f
    • 遇到panic("Panic in f")f函数停止正常执行,开始执行defer函数,按照逆序执行,先打印Second defer in f,再打印First defer in f
    • 第二个defer函数中,recover捕获到panic,打印Recovered in f: Panic in f
    • f函数结束,回到main函数,main函数继续执行,打印After calling f。因为f函数中的panicf函数内的recover捕获,所以main函数的defer函数中的recover不会捕获到异常。

执行结果:

Before calling f
Before panic in f
Second defer in f
First defer in f
Recovered in f: Panic in f
After calling f