Go语言 为什么这个程序在结果中打印421?

uinbv5nw  于 2023-01-15  发布在  Go
关注(0)|答案(1)|浏览(122)

我不明白,为什么这个程序打印421而不是431

package main

import "fmt"

var x int
func f() int {
    x++
    return x
}

func main() {
    o := fmt.Println

    defer o(f())
    defer func() {
        defer o(recover())
        o(f())
    }()

    defer f()
    defer recover()

    panic(f())
}

下面我添加了评论如何我猜:

package main

import "fmt"

var x int
func f() int {
    x++
    return x
}

func main() {
    o := fmt.Println

    defer o(f()) // x=1
    defer func() {
        defer o(recover()) // x=3 from panic (but if we ll execute this program we ll see 2)
        o(f()) // x=4
    }()

    defer f() // x=2
    defer recover() //nil

    panic(f()) // x=3
}
3zwjbxry

3zwjbxry1#

defer调用该函数,但它确实“立即”计算其参数。此外,如果从延迟函数调用recover(),则对recover()的调用仅停止死机状态(defer recover()不符合此条件)。请参阅为什么'defer recover()'不捕捉死机?
有鉴于此:我们给这些行编号:

L1: o := fmt.Println

L2: defer o(f()) // x = 1

L3: defer func() {
L4:     defer o(recover()) // recover() returns 2
L5:     o(f())             // x = 4, it gets printed
L6: }()

L7: defer f() // after panic: x = 3
L8: defer recover()

L9: panic(f()) // x = 2

上述代码的执行过程如下:

L2:评估o()的参数,f()被调用,x递增到1(稍后将打印)。o()尚未被调用。
L3:延迟函数尚未被调用,现在跳过其整个函数体。
L7:f()尚未被调用,x仍然是1
未调用L8:recover()
L9:调用f(),将x递增为2,并返回它,因此2被传递给panic()
我们处于一个恐慌状态,所以延迟的函数现在执行(以LIFO顺序)。
调用L8:recover(),但不停止恐慌状态。
L7:现在调用f(),将x递增到3
L3:现在执行这个匿名函数。
L4:recover()返回2(传递给panic()的值),这将在以后打印,但还没有,因为对o()的调用被延迟。
L5:调用f(),将x递增为4,立即打印。
L4:现在执行延迟函数o(),打印上述值2
L2:现在执行延迟函数o(),打印先前计算的值1
程序结束。

相关问题