3 回答

TA贡献1829条经验 获得超13个赞
错误很复杂,因为,嗯,错误只是很复杂。
Dave Cheney 的博客文章包括以下声明:
我得出的结论是,没有单一的方法可以处理错误。
我完全同意。考虑一些简单的事情,比如“从文件中读取数据”。这可能会失败。但是为什么它会失败,你能对这些失败做些什么吗?
以下是它可能失败的一些原因。这并不意味着是所有可能原因的完整列表,只是其中一些原因:
也许该文件不存在。它应该,但只是没有。
您可能对此无能为力。
也许该文件确实存在,但您没有访问它的权限。你应该,但你只是不这样做。
除非您具有管理员访问权限,否则您可能对此无能为力,在这种情况下,您可以授予自己权限并继续。
也许该文件存在并且您有权访问它,但数据已损坏。
对此您可能无能为力,但如果系统是自我修复的(此类系统存在),这可能是暂时的。
也许该文件暂时无法访问,因为它位于网络上并且网络已分区。
这类似于案例 3:等待和重试可能会解决问题(实际上它可能比案例 3 更有可能)。
... [他建议] 包装自定义错误类型并在自定义接口上使用类型断言。我发现这很冗长,需要大量额外的代码。
确实如此。它还需要首先产生错误的人的合作,以便您可以做出这些细微的区分。那是因为您正在处理真正复杂的硬件和软件系统。
这不是很令人满意,但这是真的。幸运的是,对于很多软件来说,很多错误情况都可以归结为“不是我的问题”:上面的前两个示例无法打开和读取某些文件(不存在或权限被拒绝)可以放入这个组。如果您正在编写文件列表实用程序或类似的东西,这可能没问题。如果您正在编写代码来运行起搏器,则停止并显示错误消息(“致命:无法报告心率”)很可能是,呃,致命的。你需要考虑上下文。

TA贡献2039条经验 获得超8个赞
如果你用 包装一个错误err
,fmt.Errorf
你可以检查错误errors.Is
例子:
var ExpectedError = errors.New("This is an error") err := fmt.Errorf("I am now wrapping %w ",ExpectedError) fmt.Println("Checking error", errors.Is(err, ExpectedError))
https://play.golang.org/p/wtOeopA-f5B

TA贡献1862条经验 获得超6个赞
错误为不应运行的代码提供了保护,并提供了处理故障后状态的方法。
Swift 和 Rust 的学习应用在惯用的 go 风格中:
在应用程序级别,我希望将所有错误集中在一个地方,以便我知道该应用程序处理哪些错误。
所有关于错误的单元测试和应用程序行为都将基于我的应用程序定义的错误类型和错误变量。为此,我必须编写从 lib 错误到 AppErrors 的转换,并在应用程序首次检查错误的任何地方使用它们。
因此,如果任何库更改或被等效库替换,则只需更改错误的转换(适应)。应用程序错误处理策略的其余部分保持原样并经过测试。
错误类型实现接口或者我们只是使用错误类型检查/切换是次要的。
这是该方法的示例。我更喜欢使用 const 来最小化强制转换。我相信这会更快、更易读。
package main
import (
"fmt"
"os"
)
type ErrorType int
const (
ReaderEndError ErrorType = iota + 1
ResourceNotFoundError
)
type AppError struct {
ErrType ErrorType
s string
error
}
func (ae AppError) Error() string {
return ae.s
}
func (ae *AppError) GetType() ErrorType {
return ae.ErrType
}
func main() {
_, err := readData("notexists")
if err != nil {
if ae, ok := err.(AppError); ok {
//should use switch case in actual startegy
if ae.ErrType == ResourceNotFoundError {
if ae.error != nil {
fmt.Println("Inner wrapped details (use for logging)", ae.error)
}
fmt.Println("handle ResourceNotFoundError here")
}
}
}
}
//sample func
func readData(file string) (*string, error) {
_, err := os.Open(file)
if err != nil {
//switch case here actually
e, _ := err.(*os.PathError)
//actually should have many helper conversion functions to do below conversions
return nil, AppError{ResourceNotFoundError, "Not found", e}
}
//assume read data
data := string("data")
return &data, nil
}
- 3 回答
- 0 关注
- 265 浏览
添加回答
举报