我最近进入Go并看过很多关于如何进行错误处理的讨论。
我看到的模式如下:
err := DoSomething()
if err != nil {
//handle
}
// continue
经常在管理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
正如您所看到的,如果从c.RegisterSomethingOnConnection
返回的错误为零,我只想运行第Connect()
行。
然而,由于提前退货,我不喜欢上述情况。早期的回报让我感到不舒服,因为从长远来看,它会损害可读性,并且在函数退出时会完全模糊。到目前为止,我的解决方案是执行以下操作:
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
我喜欢这样做有两个原因。首先,它可以防止返回零。其次,我发现它使代码更易于维护,因为您可以在返回(即日志记录)之前轻松添加功能,并且由于提前返回而没有某些路径错过添加的功能。
我做了什么是可以接受的惯用Go或者我只是需要克服我对早期回报的厌恶并遵循那种模式?
答案 0 :(得分:3)
其中一个Go Prover是:
不要只检查错误,优雅地处理错误
我建议你阅读Dave Cheney的post
我把重点放在这里:
“没有一种方法可以处理错误。相反,我认为Go的错误处理可以分为三个核心策略”
if err == ErrSomething { … }
“使用sentinel值是最不灵活的错误处理策略,因为调用者必须使用相等运算符将结果与预先声明的值进行比较。当您想要提供更多上下文时会出现问题,因为返回不同的错误会破坏平等检查。“
if err, ok := err.(SomeType); ok { … }
“错误类型是您创建的实现错误接口的类型。”
x, err := bar.Foo()
if err != nil {
return err
}
// use x
“我将此样式称为不透明的错误处理,因为虽然您知道发生了错误,但您无法查看错误内部。作为调用者,您只知道操作的结果是它有效,或者没有。“
....阅读所有帖子。
我认为错误处理的重要方面是不要只检查错误,优雅地处理它们,我希望这可以帮助你。
答案 1 :(得分:1)
您应该处理错误,或者不处理错误,但委托给它 更高级别(对呼叫者)。处理错误并将其返回 糟糕的做法好像调用者也这样做,错误可能会得到 处理了几次。
见:
Rob Pike Go. Best practice to handle error from multiple abstract level。
您可以简化它:
if err := datastore.Get(c, key, record); err != nil {
简化重复错误处理:
在Go中,错误处理很重要。语言的设计和 约定鼓励您明确检查它们的错误 发生(与其他投掷语言的惯例不同) 例外,有时会抓住它们)。在某些情况下,这使得Go 代码详细,但幸运的是,您可以使用一些技术 尽量减少重复的错误处理。
考虑具有检索的HTTP处理程序的App Engine应用程序 来自数据存储区的记录,并使用模板对其进行格式化。
func init() { http.HandleFunc("/view", viewRecord) } func viewRecord(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) key := datastore.NewKey(c, "Record", r.FormValue("id"), 0, nil) record := new(Record) if err := datastore.Get(c, key, record); err != nil { http.Error(w, err.Error(), 500) return } if err := viewTemplate.Execute(w, record); err != nil { http.Error(w, err.Error(), 500) } }