我最近开始接触 Go 并且看到了很多关于如何进行错误处理的讨论。
我看到的布局如下:
err := DoSomething()
if err != nil {
//handle
}
// continue
通常在管理 amqp 连接时,我的条件是只有在错误为零时我才想继续,因为那时我需要对连接做一些事情:
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
如您所见,如果 Connect()
返回的错误为 nil,我只想运行 c.RegisterSomethingOnConnection
行。
但是,由于提前返回,我不喜欢上面的内容。提前返回让我感到不舒服,因为从长远来看,它会损害可读性并模糊函数退出的确切时间。到目前为止,我的解决方案是执行以下操作:
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
我喜欢这样做有两个原因。首先,它防止返回 nil。其次,我发现它使代码更易于维护,因为您可以在返回之前轻松添加功能(即日志记录),并且不会有某些路径由于提前返回而错过添加的功能。
我所做的是可接受的惯用 Go 还是我只需要克服对提前返回的厌恶并遵循该模式?
最佳答案
其中一个 Go Prover 是:
不要只是检查错误,要优雅地处理它们
我推荐你阅读这篇 post来自戴夫切尼
我把亮点放在这里:
“没有单一的方法来处理错误。相反,我认为 Go 的错误处理可以分为三个核心策略”
- 哨兵错误:
if err == ErrSomething { … }
“使用标记值是最不灵活的错误处理策略,因为调用者必须使用相等运算符将结果与预先声明的值进行比较。当您想要提供更多上下文时,这会出现问题,因为会返回不同的错误会破坏相等性检查。”
- 错误类型
如果出错,ok := err.(SomeType);好的{…}
“错误类型是您创建的实现错误接口(interface)的类型。”
- 不透明的错误
x, 错误 := bar.Foo()
如果错误!=无{
返回错误
}
//使用 x
“我将这种风格称为不透明的错误处理,因为虽然您知道发生了错误,但您无法看到错误的内部。作为调用者,您所知道的操作结果是它起作用了,或者没有起作用。”
....阅读所有帖子。
我认为错误处理的重要方面是不要只是检查错误,优雅地处理它们,我希望这可以帮助到你。
关于go - 可接受的 Golang 惯用嵌套错误处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39639853/