Go中更简洁的错误处理

时间:2015-02-09 11:50:54

标签: error-handling exception-handling go

如何在Go中处理很多错误?

我查看我的代码并发现它充满了错误处理程序:

err = result.Scan(&bot.BID, &bot.LANGUAGE, &bot.SOURCE)
if err != nil {
    log.Fatalf("result.Scan: %v", err)
    return
}

fileName, err := copySourceToTemporaryFile(bot)
if err != nil {
    log.Fatalf("copySourceToTemporaryFile: %v", err)
    return
}
...

很多行看起来像:

// do something
// handle error
// handle error
// handle error

// do something 2
// handle error
// handle error
// handle error

我是否可以创建一个默认处理程序来打印错误并停止处理,或至少移出这个" error-handler-garbage"出于我的代码逻辑?

2 个答案:

答案 0 :(得分:5)

让我想起Rob Pike最近的Errors are values,以及Mr. Rob Pike taught me about practice of error handling in Go at GoCon 2014

  

然而,关键的一课是,错误是价值,Go编程语言的全部功能可用于处理它们。

     

值得强调的是,无论设计如何,程序检查错误都是至关重要的。这里的讨论不是关于如何避免检查错误,而是关于使用语言来处理错误。

一种技术是定义一个名为errWriter的对象:

type errWriter struct {
    w   io.Writer
    err error
}
  

write方法调用底层Writer的Write方法,并记录第一个错误以供将来参考:

func (ew *errWriter) write(buf []byte) {
    if ew.err != nil {
        return
    }
    _, ew.err = ew.w.Write(buf)
}
  

一旦发生错误,write方法就会变为无操作,但会保存error值。

     

给定errWriter类型及其write方法,可以重构上面的代码:

ew := &errWriter{w: fd}
ew.write(p0[a:b])
ew.write(p1[c:d])
ew.write(p2[e:f])
// and so on
if ew.err != nil {
    return ew.err
}

答案 1 :(得分:1)

如果error是“真实的”,如果您不希望在运行时出现意外的恐慌,则应该(必须)处理它。

为了补充VonC关于errWriter技术的答案,在更多情况下您可以减少错误处理代码:

如果您知道即使函数或方法 可以返回error也不会(例如,您提供来自源代码的参数,你知道它们会起作用)。在这些情况下,您(或库的作者)可以提供帮助函数(或方法),这些函数不会返回error,但如果仍然发生则会引发运行时混乱。

这些包的好例子是templateregexp包:如果在编译时提供有效的模板或正则表达式,则可以确保在运行时始终可以无错误地解析它们。出于这个原因,template包提供Must(t *Template, err error) *Template函数,regexp包提供MustCompile(str string) *Regexp函数:它们不返回error因为它们的预期用途是输入保证有效的地方。

示例:

// "text" is a valid template, parsing it will not fail
var t = template.Must(template.New("name").Parse("text"))

// `^[a-z]+\[[0-9]+\]$` is a valid regexp, always compiles
var validID = regexp.MustCompile(`^[a-z]+\[[0-9]+\]$`)