当recover() 是空操作时?

问题描述 投票:0回答:1

参考:https://go101.org/quizzes/panic-recover-1.html

package main

import "fmt"

func ExamplePanicGo101_1() {
    defer func() {
        fmt.Print(recover()) // catch panic(1)
    }()

    defer func() {
        defer fmt.Print(recover()) // catch panic(2)
        defer panic(1)
        recover() // no-op - B, should be called inside deferred function,
    }()

    defer recover() // no-op - A, should be called inside deferred function,
    panic(2)
    // Output:
    // 21
}

测试通过。

问题:

  • 我可以理解
    no-op - A
    是无操作的,因为它不是在延迟函数内部调用的,但是
    no-op - B
    是无操作的吗?由于它是在延迟函数内部调用的,所以我认为它应该捕获
    panic(2)
    ,但没有。
go deferred
1个回答
0
投票

我想你可能错过了以下

defer

每次执行“defer”语句时,调用的函数值和参数都会照常评估并重新保存,但不会调用实际函数。

所以执行时

defer fmt.Print(recover()) // catch panic(2)
defer panic(1)
recover() // no-op - B, should be called inside deferred function,

步骤是:

  • 评估
    recover()
    ,并有效地评估
    defer fmt.Print(2)
    (因为
    recover()
    评估为
    2
    )。
  • defer panic(1)
  • recover()
    - nooop,因为没有活跃的恐慌
  • 执行延迟
    panic(1)
  • 执行延迟
    fmt.Print(2)
    记住“由 F 延迟的任何函数都会照常执行”)

以下示例可能会有所帮助:

package main

import "fmt"

func main() {
    defer func() {
        fmt.Println(recover()) // catch panic(1)
    }()

    defer func() {
        fmt.Println("a")
        defer fmt.Println(fmt.Println("a1")) // The "a1" will print between a and b (note `3 nil` will be printed later, this is the return from the inner fmt.Println)
        defer fmt.Println(recover())         // catch panic(2)
        fmt.Println("b")
        defer panic(1)
        fmt.Println("c")
        recover() // no-op - B, should be called inside deferred function,
    }()

    defer recover() // no-op - A, should be called inside deferred function,
    panic(2)
    // Output:
    // a
    // a1
    // b
    // c
    // 2
    // 3 <nil>
    // 1
}
© www.soinside.com 2019 - 2024. All rights reserved.