Go 返回自定义错误类型与仅创建新错误

Go 返回自定义错误类型与仅创建新错误,go,Go,让我们假设为了简单起见,我有一个简单的函数,它只是尝试根据作为参数传递的字符串打开一个文件(不要依赖于文件打开过程的简单性,因为实际示例将更加复杂) func retrieveConfig(fs.Filesystem,app string)(规范,错误){ var v规格 文件名:=“发布/”+app+“.yaml” 文件,错误:=fs.Open(文件名) 如果错误!=零{ errOpenFile:=ErrOpeningConfigFile{filename} 返回规范{},新文件{filena

让我们假设为了简单起见,我有一个简单的函数,它只是尝试根据作为参数传递的字符串打开一个文件(不要依赖于文件打开过程的简单性,因为实际示例将更加复杂)

func retrieveConfig(fs.Filesystem,app string)(规范,错误){
var v规格
文件名:=“发布/”+app+“.yaml”
文件,错误:=fs.Open(文件名)
如果错误!=零{
errOpenFile:=ErrOpeningConfigFile{filename}
返回规范{},新文件{filename}
}
下面是我正在使用的自定义错误的定义

type ErrOpeningConfigFile struct {
    s string
}

func (errConfigFileNotFound *ErrOpeningConfigFile) Error() string {
    return fmt.Sprintf("Error opening configuration file %s")
}
我考虑采用这种方法,因为我的想法是它将提供更多的覆盖范围,并使核心更易于测试

现在我可以更容易地测试错误路径,因为我可以在单元测试中的自定义错误上键入assert

然而,这肯定会增加代码库

我想另一种方法是

返回nil,errors.New(“未找到配置文件”)
这将限制代码,但会使测试更笨拙(或范围更窄)


进行此操作的适当方式(或惯用方式)是什么?

fmt.Errorf(“无法打开配置文件:%w”,err)这个问题太长了,读不下去了。我已经在博客上写了一篇关于这个话题的博客文章,大概有2000个字。TL;Dr;它取决于。在大多数情况下,一个简单的答案提供了必要的灵活性:简单地把你的错误包成@ ZekMs建议。ver已经准备好了。但是,您仍然不能对
fmt.Errorf
返回的错误键入assert,对吗?您可以添加更多上下文。使用
:%w
包装器,您可以使用
errors.is
errors.As
(如果您使用的是最新的Go,这些是1.13中的新版本;对于较旧的版本,有golang.orgx/errors).fmt.Errorf(“无法打开配置文件:%w”,错误)这个问题太长了,读不下去了。我已经在博客上写了一篇关于这个话题的博客文章,大概有2000个字。TL;Dr;它取决于。在大多数情况下,一个简单的答案提供了必要的灵活性:简单地把你的错误包成@ ZekMs建议。ver已经准备好了。但是,您仍然不能对
fmt.Errorf
返回的错误键入assert,对吗?您可以添加更多上下文。使用
:%w
包装器,您可以使用
errors.is
errors.As
(如果您使用的是最新的Go,这些是1.13中的新版本;对于较旧的版本,有golang.orgx/errors)。