如何在恐慌的 Go 函数中返回一个值?
Posted
技术标签:
【中文标题】如何在恐慌的 Go 函数中返回一个值?【英文标题】:How to return a value in a Go function that panics? 【发布时间】:2016-01-15 00:25:46 【问题描述】:我的 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?
【问题讨论】:
【参考方案1】:使用 icza 的答案中的示例,如果您想知道 如果您从恐慌中恢复但不为命名的 return 分配值会发生什么,如下所示:
func main()
fmt.Println("Returned:", MyFunc()) // false
func MyFunc() (ret bool)
defer func()
if r := recover(); r != nil
()
panic("test")
return true
函数将返回指定返回类型的零值。
运行Go Playground中的示例
【讨论】:
【参考方案2】:您可以使用named result parameters。命名您的返回值,并在检测到恐慌时的延迟函数中,您可以更改返回“变量”的值。将返回更改后的新值。
例子:
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中提到了这个:
例如,如果延迟函数是 function literal 并且周围的函数有 named result parameters 在字面量内,则延迟函数可以在返回结果参数之前访问和修改结果参数。
博文Defer, Panic and Recover中也提到过:
延迟函数可以读取并分配给返回函数的命名返回值。
还有Effective Go: Recover:
如果
doParse
发生紧急情况,恢复块会将返回值设置为nil
——延迟函数可以修改命名的返回值。
【讨论】:
我对如果没有命名返回值会返回什么感兴趣。玩你的playground,好像是type的零值 @KyleChadha 是的,如果结果未命名并且未达到return
语句(例如由于恐慌),则返回结果类型的零值。这在Why can a normal return hide a panic that a named return correctly provides to the caller?中有详细说明以上是关于如何在恐慌的 Go 函数中返回一个值?的主要内容,如果未能解决你的问题,请参考以下文章
go中defer的理解--deferreturn返回值之间执行顺序
Go MySQL 中的错误:func (*Rows) Scan 返回恐慌:(func() string)