为什么正常的退货会隐藏命名的退货正确提供给呼叫者的恐慌? [英] Why can a normal return hide a panic that a named return correctly provides to the caller?

查看:57
本文介绍了为什么正常的退货会隐藏命名的退货正确提供给呼叫者的恐慌?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

package main

import (
    "fmt"
    "log"
)

func catch(err *error) {
    if r := recover(); r != nil {
        *err = fmt.Errorf("recovered panic: %v", r)
    }
}

func panicIf42(n int) {
    if n == 42 {
        panic("42!")
    }
}

func NormalReturns(n int) error {
    var err error
    defer catch(&err)
    panicIf42(n)
    return err
}

func NamedReturns(n int) (err error) {
    defer catch(&err)
    panicIf42(n)
    return
}

func main() {
    err := NamedReturns(42)
    log.Printf("NamedReturns error: %v", err)
    err = NormalReturns(42)
    log.Printf("NormalReturns error: %v", err)
}

输出:

2009/11/10 23:00:00 NamedReturns error: recovered panic: 42!
2009/11/10 23:00:00 NormalReturns error: <nil>

游乐场链接

NormalReturns返回nil错误,但我希望NamedReturns和NormalReturns都返回非nil错误.

NormalReturns returns a nil error, but I would expect both NamedReturns and NormalReturns to return a non-nil error.

我认为命名的returns只是一种代码可读性功能,可以为您声明和初始化return,但似乎还有更多功能.我想念什么?

I thought named returns was just a code readability feature that declares and initializes returns for you, but it seems there's more to it. What am I missing?

推荐答案

我认为命名的returns只是一种代码可读性功能,可以为您声明和初始化return,但似乎还有更多功能.我想念什么?

I thought named returns was just a code readability feature that declares and initializes returns for you, but it seems there's more to it. What am I missing?

如果命名结果参数,则返回给调用方时它们的实际值将确定返回的值.这意味着您可以像其他局部变量一样更改它们的值,并且如果return语句的表达式列表为空,则将使用它们的最后分配值.同样,如果有延迟函数,它们可以在return语句之后的 之前的函数返回其调用方的过程中修改命名结果参数的值,这些修改将被保存.它也允许在出现紧急情况时修改返回值,请参见

If you name the result parameters, their actual value at the time of returning to the caller will determine the returned values. Meaning you can change their values like other local variables, and if the expression list of the return statement is empty, their last assigned values will be used. Also if there are deferred functions, they can modify the values of the named result parameters after the return statement and before the function returns to its caller, and those modifications will be preserved. It also allows to modify return values in case of a panic, see How to return a value in a Go function that panics?

规范:返回语句:

无论如何声明[返回值],所有结果值都将初始化为零值表示其在输入函数时的类型.指定结果的"return"语句在执行任何延迟函数之前会设置结果参数.

Regardless of how they [the return values] are declared, all the result values are initialized to the zero values for their type upon entry to the function. A "return" statement that specifies results sets the result parameters before any deferred functions are executed.

规范:延迟声明:

例如,如果延迟函数是函数文字,并且周围函数具有命名结果参数,延迟函数可以在访问和修改结果参数之前对其进行访问和修改返回.

For instance, if the deferred function is a function literal and the surrounding function has named result parameters that are in scope within the literal, the deferred function may access and modify the result parameters before they are returned.

NormalReturns()中:返回值被初始化为其零值(对于所有接口类型,包括内置

In NormalReturns(): The return value is initialized to its zero value (which is nil for all interface types, including the builtin error type), and since the return statement is not reached (due to a panic in panicIf42()), it will stay nil. It doesn't matter if the local variable err is changed, that is not the result variable. It's just an ordinary variable. It will have no effect on the value returned

通常,如果一个函数没有命名结果变量,并且该函数没有到达return语句(例如由于紧急情况),则它的返回值不能为零(与零不同).结果类型的值.

In general, if a function does not have named result variables, and if this function does not reach a return statement (e.g. due to a panic), it cannot have return values other than (meaning different from) the zero values of the result types.

NamedReturns()中,延迟的catch()将修改命名结果变量err.更改是保留的":函数结束时将返回任何命名结果变量所保存的内容(如果存在,则在调用延迟函数之后发生).因此,即使这里也未到达return语句,catch()函数也会更改err结果变量,并且分配给它的任何内容都将用作返回的值.

In NamedReturns() the deferred catch() will modify the named result variable err. The changes are "preserved": whatever the named result variables hold will be returned when the function ends (which happens after calling deferred functions, if there are any). So even though the return statement is not reached here either, the catch() function changes the err result variable, and whatever is assigned to it will be used as the value returned.

有关该主题的更多信息:

More on the topic:

转到博客:推迟,紧急和恢复:

延迟的函数可以读取并分配给返回函数的命名返回值.

Deferred functions may read and assign to the returning function's named return values.

以及有效的Go:恢复:

如果doParse出现紧急情况,恢复块会将返回值设置为nil-延迟函数可以修改命名的返回值.

If doParse panics, the recovery block will set the return value to nil—deferred functions can modify named return values.

这篇关于为什么正常的退货会隐藏命名的退货正确提供给呼叫者的恐慌?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆