Error handling Go中更简洁的错误处理
如何处理围棋中的大量错误 我查看了我的代码,发现其中充满了错误处理程序:Error handling Go中更简洁的错误处理,error-handling,exception-handling,go,Error Handling,Exception Handling,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.Fata
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
我可以创建一个默认的处理程序来打印错误并停止处理,或者至少将这个“错误处理程序垃圾”从我的代码逻辑中移出吗?这让我想起了Rob Pike最近的一个错误处理程序,以及 然而,关键的教训是错误是值,Go编程语言的全部功能可用于处理它们 值得强调的是,无论设计如何,程序都必须检查错误,无论它们是如何暴露的。这里的讨论不是关于如何避免检查错误,而是关于使用语言优雅地处理错误 一种技术是定义一个名为
errWriter
的对象:
type errWriter struct {
w io.Writer
err error
}
write
方法调用底层Writer
的write方法,并记录第一个错误以供将来参考:
一旦发生错误,write
方法将变为no op,但error
值将被保存
给定errWriter
类型及其写入方法,可以重构上述代码:
如果
错误
是“真实的”,如果不希望在运行时出现意外的恐慌,您应该(必须)处理它
为了补充VonC关于errWriter
技术的回答,您可以在更多情况下减少错误处理代码:
在这些情况下,您知道即使函数或方法可能返回错误
,它也不会返回(例如,您从源代码中提供参数,您知道这些参数可以工作)。在这些情况下,您(或库的作者)可以提供帮助函数(或方法),这些函数不会返回错误
,但如果错误仍然发生,会引发运行时死机
和包就是很好的例子:如果您在编译时提供了有效的模板或regexp,那么您可以确保在运行时对它们进行解析时不会出错。因此,模板
包提供函数,regexp
包提供函数:它们不会返回错误
s,因为它们的预期用途是保证输入有效的地方
示例:
// "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]+\]$`)
我以前读过。如果我调用的方法不仅返回错误,而且还返回不同类型的结构,那会怎么样?一开始看起来很难看(后来也一样),但我恰好喜欢这种错误捕获。这真的让我想到:“在这种情况下,我应该怎么做?我应该崩溃(致命),我应该继续使用其他方法/默认值,还是应该询问用户”。如果您执行
log.Fatalf()
操作,您可以定义一个方法CrashIfErr(errerror)
,只需调用log.Fatalf()
。顺便说一句:在log.Fatalf()
之后不需要return
。我喜欢Mustxxx
方法,它可以简化错误管理并澄清期望+1.
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
}
// "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]+\]$`)