如何 return 恐慌的 Go 函数中的值?
How to return a value in a Go function that panics?
我的 Go 函数需要 return 一个值,但在调用库函数时可能会崩溃。我可以使用 recover()
在延迟调用中捕获它,但是在这种情况下我如何 return 一个值?
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?
}
您可以使用 named result parameters。命名您的 return 值,并且在检测到恐慌时的延迟函数中,您可以更改 return "variables" 的值。更改后的新值将 returned.
示例:
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"
}
输出(在 Go Playground 上尝试):
Returned: was panic, recovered value: test
这个在Spec: Defer statements中提到:
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.
博客里也提到了post Defer, Panic and Recover:
Deferred functions may read and assign to the returning function's named return values.
If doParse
panics, the recovery block will set the return value to nil
—deferred functions can modify named return values.
使用 icza 的回答中的示例,如果您想知道会发生什么 如果您从恐慌中恢复过来但不为指定的 return 分配值,像这样:
func main() {
fmt.Println("Returned:", MyFunc()) // false
}
func MyFunc() (ret bool) {
defer func() {
if r := recover(); r != nil {
}
}()
panic("test")
return true
}
函数将return指定return类型的零值。
运行中的例子Go Playground
您可以像这样使用命名参数:
func main() {
fmt.Println("Returned:", MyFunc())
}
func MyFunc() (err error) {
defer func() {
if r := recover(); r != nil {
err=convertRecoverToError(r)
}
}()
panic("test")
return nil
}
func ConvertRecoverToError(r interface{}) error {
switch x := r.(type) {
case string:
return errors.New(x)
case error:
return x
default:
return errors.New(fmt.Sprint(x))
}
}
我的 Go 函数需要 return 一个值,但在调用库函数时可能会崩溃。我可以使用 recover()
在延迟调用中捕获它,但是在这种情况下我如何 return 一个值?
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?
}
您可以使用 named result parameters。命名您的 return 值,并且在检测到恐慌时的延迟函数中,您可以更改 return "variables" 的值。更改后的新值将 returned.
示例:
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"
}
输出(在 Go Playground 上尝试):
Returned: was panic, recovered value: test
这个在Spec: Defer statements中提到:
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.
博客里也提到了post Defer, Panic and Recover:
Deferred functions may read and assign to the returning function's named return values.
If
doParse
panics, the recovery block will set the return value tonil
—deferred functions can modify named return values.
使用 icza 的回答中的示例,如果您想知道会发生什么 如果您从恐慌中恢复过来但不为指定的 return 分配值,像这样:
func main() {
fmt.Println("Returned:", MyFunc()) // false
}
func MyFunc() (ret bool) {
defer func() {
if r := recover(); r != nil {
}
}()
panic("test")
return true
}
函数将return指定return类型的零值。
运行中的例子Go Playground
您可以像这样使用命名参数:
func main() {
fmt.Println("Returned:", MyFunc())
}
func MyFunc() (err error) {
defer func() {
if r := recover(); r != nil {
err=convertRecoverToError(r)
}
}()
panic("test")
return nil
}
func ConvertRecoverToError(r interface{}) error {
switch x := r.(type) {
case string:
return errors.New(x)
case error:
return x
default:
return errors.New(fmt.Sprint(x))
}
}