2 回答
TA贡献1803条经验 获得超6个赞
为了详细说明 FUZxxl 的解释,go 区分了错误(可能出错的事情确实出错了)和异常(不可能出错的事情实际上出错了)。
区别有时可能很微妙(因为它依赖于“意外”),但它也可能比您在其他语言中看到的“一切都是例外”更清晰。
例如,考虑可能溢出的整数。一种可能性是将其视为“正常”行为,应适当处理:
func safe_add(x, y uint32) (uint32, error) {
z := x + y
if z < x || z < y {
return 0, fmt.Errorf("Integer overflow")
}
return z, nil
}
另一个是考虑它“永远不会发生”,并panic在万一发生时在不太可能的情况下运行运行时:
func panic_add(x, y uint32) uint32 {
z, err := safe_add(x, y)
if err != nil {
panic(err)
}
return z
}
(请注意,我在这里使用了我自己的“safe_add”,但您当然不必这样做)
主要区别在于您之后处理错误的方式。添加一个数字到它自己直到它溢出errors 给出:
func safeloop(u uint32) {
var err error
for {
if u, err = safe_add(u, u); err != nil {
fmt.Println(err)
return
} else {
fmt.Println(u)
}
}
}
处理恐慌时使用recover内置函数:
func panicloop(u uint32) {
defer func() {
if err := recover(); err != nil {
fmt.Println(err)
}
}()
for {
u = panic_add(u, u)
fmt.Println(u)
}
}
(操场上的完整示例)
请注意,恐慌版本有一个更简单的循环,因为您基本上从不期望任何错误并且从不检查错误。与此相反的是,处理恐慌的方法非常麻烦,即使是这样一个非常简单的例子。您defer是一个函数,它会recover在错误出现并脱离函数时调用并捕获错误。当你的代码变得更复杂,跟踪确切位置/恐慌是如何产生并作用于它因此可以成为很多比他们可能出现的地方检查错误,与更复杂result, err := func_which_may_fail(...)的图案。
您甚至可以在恐慌之间交替,恢复哪些返回错误,将错误转换为恐慌,......但这(可以理解)被认为是糟糕的设计。
go 博客上有一些关于错误处理和恐慌的好资源。该规范是读的好。
在您的情况下,由于您期望“服务器已关闭”是一种非常频繁的行为,因此您绝对应该error按照 FUZxxl 的建议行事,但我希望这可能对您(或其他人)了解错误处理的工作原理有用在去。
- 2 回答
- 0 关注
- 213 浏览
添加回答
举报