Golang idomatic嵌套错误处理

Fuz*_*ker 6 idioms idiomatic go

我最近进入Go并看到了很多关于如何进行错误处理的讨论.

我看到的模式如下:

err := DoSomething()
if err != nil {
   //handle
}
// continue
Run Code Online (Sandbox Code Playgroud)

经常在管理amqp连接时,我的条件是我只想在错误为nil时继续,因为那时我需要在连接上做一些事情:

c, err := Connect()
if err != nil {
   return nil, err
}
s,err := c.RegisterSomethingOnConnection()
if err != nil {
   return nil, err
}
val, err := s.DoSomething()
return val, err
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,c.RegisterSomethingOnConnection如果返回的错误Connect()是nil,我只想运行该行.

但是,由于提前退货,我不喜欢上述情况.早期的回报让我感到不舒服,因为从长远来看,它会损害可读性,并且在功能退出时会完全模糊.到目前为止,我的解决方案是执行以下操作:

var err error
var val ReturnType

c,err := Connect()
if err == nil {
    s,err := c.RegisterSomethingOnConnection()
    if err == nil {
       val,err = s.DoSomething()
    }
}
return val,err
Run Code Online (Sandbox Code Playgroud)

我喜欢这样做有两个原因.首先,它可以防止返回零.其次,我发现它使代码更易于维护,因为您可以在返回(即日志记录)之前轻松添加功能,并且由于提前返回而没有某些路径错过添加的功能.

是我做了什么可以接受惯用Go或者我只是需要克服我对早期回报的厌恶并遵循那种模式?

Edd*_*dez 8

Go Prover 之一是:

\n\n

Don\xe2\x80\x99t 只是检查错误,优雅地处理它们

\n\n

我建议您阅读戴夫·切尼的这篇文章

\n\n

我把重点放在这里:

\n\n

“错误处理没有单一的方法。相反,我认为 Go\xe2\x80\x99s 错误处理可以分为三个核心策略”

\n\n
    \n
  • 哨兵错误:
  • \n
\n\n

if err == ErrSomething { \xe2\x80\xa6 }

\n\n

“使用哨兵值是最不灵活的错误处理策略,因为调用者必须使用相等运算符将结果与预先声明的值进行比较。当您想要提供更多上下文时,这会出现问题,因为返回不同的错误将破坏相等检查”。

\n\n
    \n
  • 错误类型
  • \n
\n\n

if err, ok := err.(SomeType); ok { \xe2\x80\xa6 }

\n\n

“错误类型是您创建的实现错误接口的类型。”

\n\n
    \n
  • 不透明的错误
  • \n
\n\n

\nx, err := bar.Foo()\n if err != nil {\n return err\n }\n// use x\n

\n\n

“我将这种风格称为不透明错误处理,因为虽然您知道发生了错误,但您没有能力看到错误的内部。作为调用者,您所知道的操作结果是有效,或者没有\xe2\x80\x99t。”

\n\n

....阅读所有帖子。

\n\n

我认为错误处理的重要方面是Don\xe2\x80\x99t 只是检查错误,优雅地处理它们,我希望这可以帮助你。

\n