Go 将恐慌/恢复视为抛接球是错误的吗

Go 将恐慌/恢复视为抛接球是错误的吗,go,Go,作为一个新的围棋爱好者,试图用围棋的方式处理错误。说清楚一点,我喜欢例外 我有一个服务器,它接受连接,处理一组请求并回复它们。我发现我能做到 if err != nil{ panic(err) } 在深层处理代码中 而且 defer func() { if err := recover(); err != nil { log.Printf("%s: %s", err, debug.Stack()) // line 20 }

作为一个新的围棋爱好者,试图用围棋的方式处理错误。说清楚一点,我喜欢例外

我有一个服务器,它接受连接,处理一组请求并回复它们。我发现我能做到

if err != nil{
      panic(err)
}
在深层处理代码中

而且

defer func() {
        if err := recover(); err != nil {
            log.Printf("%s: %s", err, debug.Stack()) // line 20
        }
    }()
在客户端连接代码中(每个连接都在一个goroutine中)。这很好地包装了一切,强制关闭了连接(其他延迟启动),我的服务器继续嗡嗡地运行

但这感觉非常像一个抛接球场景——golang表示它不支持这种场景。问题

  • 这是稳定的。恢复恐慌是一件可以做的事 持续的生活方式。它的目的并不是只是稍微推迟一个决定 立即关闭
  • 我找了一个关于这个话题的讨论,但在任何地方都找不到——有什么建议吗

我觉得答案是“是的,它可以工作”,并且可以在您自己的代码中使用,但是恐慌不应该被用于更广泛的用途的库中。库行为的标准和礼貌方式是通过错误返回

通常大多数方法不会死机,而是返回一个错误,并且使用defer会有一点开销


是的,它确实有效,但是“正确的”/“执行”方式是返回错误,而不是使用panic/recover。

是的,您可以按照您的建议执行。在标准包中,有些情况下会使用panic/recover来处理错误。各国:

有关恐慌恢复的真实示例,请参阅json包 来自Go标准库。它使用一个集合对JSON编码的数据进行解码 递归函数的定义。当遇到格式错误的JSON时,解析器 调用panic以将堆栈展开到顶级函数调用,该调用 从死机中恢复并返回适当的错误值(请参阅 中decodeState类型的“error”和“unmarshal”方法 解码,开始)

一些建议:

  • 对于您的正常用例,请使用
    error
    。这应该是您的默认设置
  • 如果您的代码通过使用
    panic
    /
    recover
    (例如使用递归调用堆栈)变得更清晰、更简单,那么请将其用于该特定情况
  • 千万不要让包裹泄漏,以免引起恐慌。包中使用的恐慌应该在包中恢复,并作为错误返回
  • 从恐慌中恢复是稳定的。不要担心恢复后继续执行。您可以在标准库中看到这种行为,例如使用
    net/http
    包,该包从处理程序中的恐慌中恢复,以防止在单个请求出现恐慌时整个http服务器崩溃

正如您所知,
debug.Stack
已被弃用。使用
runtime.Stack
来代替一个非常大的缓冲区。使用异常范例在Go中开发,而不是在每一行代码上进行if检查,这将非常好(可能每个命令都会失败)。我想说的一个异常是数学包。错误值的折衷是,您不能再在forumulas中使用数学函数,有时为了方法链接而对“不可能发生”的输入感到恐慌是有意义的。通常情况下,数学包中的“不可能发生”输入是不可恢复状态的标志。(当然,应该清楚地记录恐慌的情况)。“Go库中的惯例是,即使包在内部使用恐慌,其外部API仍会显示显式的错误返回值。”——。我想我看到一些内置模块/库打破了这个惯例。例如,数组索引超出范围就是一种恐慌。