【问题标题】:How to return a value in a Go function that panics?如何在恐慌的 Go 函数中返回一个值?
【发布时间】: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?
}

【问题讨论】:

    标签: go exception-handling recover


    【解决方案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——延迟函数可以修改命名的返回值。

      【讨论】:

      猜你喜欢
      • 2019-08-27
      • 1970-01-01
      • 1970-01-01
      • 2022-01-22
      • 2019-10-07
      • 2022-01-25
      • 2018-10-28
      • 1970-01-01
      • 2021-09-15
      相关资源
      最近更新 更多