如何在一个恐慌的Go函数中返回一个值?

Neo*_*ang 9 exception-handling recover go

我的Go函数应该返回一个值,但在调用库函数时可能会出现混乱.我可以用来recover()在延期调用中捕获它,但是在这种情况下如何返回值?

func MyFunc() string{
    defer func() {
        if err := recover(); err != nil {
            // What do I do to make MyFunc() return a value in case of panic?
        }
    }()
    SomeFuncThatMayPanic()
    return "Normal Return Value"
    // How can I return "ERROR" in case of panic?
}
Run Code Online (Sandbox Code Playgroud)

icz*_*cza 31

您可以使用命名结果参数.命名您的返回值,并在检测到恐慌时的延迟函数中,您可以更改返回"变量"的值.将返回更改的新值.

例:

func main() {
    fmt.Println("Returned:", MyFunc())
}

func MyFunc() (ret string) {
    defer func() {
        if r := recover(); r != nil {
            ret = fmt.Sprintf("was panic, recovered value: %v", r)
        }
    }()
    panic("test")
    return "Normal Return Value"
}
Run Code Online (Sandbox Code Playgroud)

输出(在Go Playground上试试):

Returned: was panic, recovered value: test
Run Code Online (Sandbox Code Playgroud)

这在Spec:Defer语句中提到:

例如,如果延迟函数是函数文字并且周围函数已命名在文字范围内的结果参数,则延迟函数可以在返回结果参数之前访问和修改结果参数.

Defer,Panic和Recover博客文章中也提到了这一点:

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

而且在Effective Go:Recover:

如果doParse发生nil混乱,恢复块会将返回值设置为-deferred函数,可以修改命名返回值.