Go提供了两种处理错误的方法,但我不确定使用哪种错误。
假设我实现了一个经典的ForEach
函数,它接受一个切片或一个映射作为参数。要检查是否传入了iterable,我可以这样做:
func ForEach(iterable interface{}, f interface{}) {
if isNotIterable(iterable) {
panic("Should pass in a slice or map!")
}
}
或
func ForEach(iterable interface{}, f interface{}) error {
if isNotIterable(iterable) {
return fmt.Errorf("Should pass in a slice or map!")
}
}
我看到一些讨论说panic()
应该避免,但人们也说如果程序无法从错误中恢复,那么你应该panic()
。
我应该使用哪一个?选择正确的主要原则是什么?
答案 0 :(得分:26)
来自Dave Cheney:
panics
对您的计划来说总是致命的。在惊慌中你永远不会假设 你的来电者可以解决问题。因此panic
仅用于。{ 特殊情况,在你不可能的情况下 代码或任何整合代码的人都可以继续。
对于整个程序,或者至少对于当前的goroutine,您应该假设恐慌将立即致命。问问自己“当这种情况发生时,应用程序是否会立即崩溃?”如果是,请使用恐慌;否则,请使用错误。
答案 1 :(得分:4)
使用panic
。
因为您的用例是滥用API 。如果程序正确调用了API,则永远不会在运行时发生这种情况。
实际上,如果删除了测试,则任何使用正确参数调用API的程序的行为都将与相同。该测试仅在早期失败,并显示一条错误消息,该错误消息对执行此错误的程序员有所帮助。理想情况下,在运行测试套件时,在开发过程中可能会出现一次恐慌,程序员甚至可以在提交错误代码之前就修复该调用,并且这种错误使用永远不会达到生产目的。
另请参阅this reponse来质疑使用错误验证函数参数是否是Go中的一种好模式?。
答案 2 :(得分:1)
我喜欢在某些库中完成此操作的方式,这些库在常规方法DoSomething
之上,其“ panicky”版本添加了MustDoSomething
。我是go
的新手,但我已经在多个地方看到过它,尤其是sqlx
。
通常,如果您想将代码公开给其他人,则应该拥有Must-
和该方法的常规版本,或者您的方法/函数应该使客户端有机会恢复他们想要的方式,因此error
应该以{{1}}惯用的方式提供给他们。
话虽如此,我同意,如果您的API /库使用不当,恐慌也可以。实际上,我还看到过go
之类的方法,如果缺少关键的env.var,它们会惊慌。基本上是故障切换机制。
答案 3 :(得分:0)
答案 4 :(得分:0)
如果在启动服务时没有提供某些强制性要求(例如数据库连接,需要一些服务配置),那么你应该使用恐慌。
任何用户响应或服务器端错误都应该返回错误。
答案 5 :(得分:0)
问自己以下问题:
答案 6 :(得分:0)
我更喜欢使用紧急情况,这使得代码逻辑更易于编写和调试。请参阅下面的两个链接:
答案 7 :(得分:-2)
不要使用恐慌来进行正常的错误处理。使用错误和多个返回值。请参阅https://golang.org/doc/effective_go.html#errors。