当调用`recover()`时,返回给调用者什么值?

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

首先请注意,这个问题是故意标记的

#language-lawyer

  • 需要相对严格的理论(而非经验)讨论。

  • 下面我们以语言规范作为讨论的参考。

1.简介

严格来说

f1()
f2()
的调用者会返回什么值?

//`T` is some type.
func f1() T {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("recover")
        }
    }()
    g() //panics
    return something
}
//`T` is some type.
func f2() (v T) {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("recover")
        }
    }()
    v = X //assignment
    g() //panics
    return something
}

据我测试,

f1()
返回
T
的零值,
f2()
返回
X

2.问题

该行为是否由规范或 UB 保证(未定义行为)? (后一种情况可以改写为“是否允许实现一个 Go 编译器,使

f1()
返回,例如,
T
类型的统一随机值?”)

处理恐慌说(强调我的):

recover 函数允许程序管理恐慌 goroutine 的行为。假设函数 G 推迟了调用恢复的函数 D,并且与 G 执行的同一 goroutine 上的函数中发生了恐慌。当延迟函数运行到D时,D调用recover的返回值将是传递给panic调用的值。如果 D 正常返回,而没有引发新的恐慌,则恐慌序列将停止。在这种情况下,G 和恐慌调用之间调用的函数的状态将被丢弃,并恢复正常执行。然后,G 在 D 之前推迟的任何函数都会运行,并且 G 的执行通过返回到其调用者而终止。

它根本没有解释什么值将具体返回给

G
的调用者。

go language-lawyer
1个回答
0
投票

在规范的

Return statements
部分中指出:

无论如何声明它们,所有结果值在进入函数时都会被初始化为其类型的零值。在执行任何延迟函数之前,指定结果集的“return”语句设置结果参数。

因此,除非您通过

return
语句或修改命名结果参数来更改它们,否则将返回零值。

© www.soinside.com 2019 - 2024. All rights reserved.