gon*_*opp 2 string error-handling formatting go
双方%s并%v可以用来在Go格式错误,而且似乎没有功能上的差异,至少在表面上。
我们在 Go 自己的工具中看到了两者。
在cmd/go/internal/get/path.go 中:
return fmt.Errorf("malformed import path %q: %v", path, err)
在cmd/go/internal/list/list.go 中:
base.Fatalf("%s", err)
我应该更喜欢一个吗?
我应该使用 %s 还是 %v 来格式化错误?
TL; 博士; 两者都不。使用%w的病例99.99%。在案件的其他0.001%,%v而%s可能是“应该”的行为一样,当误差值除外nil,但没有保证。%vfor nilerrors更友好的输出可能是更喜欢的原因%v(见下文)。
现在了解详情:
%w代替%v或%s:从 Go 1.13 开始(或更早,如果您使用golang.org/x/xerrors),您可以使用%w动词,仅用于error值,它包装错误,以便以后可以用 解开errors.Unwrap,这样就可以考虑用errors.Is和errors.As。
唯一不合适的时候:
xerrors这不是一个选项。Not found在搜索用户时从数据库中收到错误,并希望将其转换为Unauthorized响应。但是,在这种情况下,您很少会将原始错误值与任何格式动词一起使用。%v和%s呢?文档中提供了有关如何实施%s和%v实施的详细信息。我已经突出显示了与您的问题相关的部分。
如果操作数是一个reflect.Value,则操作数被它所持有的具体值替换,并且打印继续下一个规则。
如果一个操作数实现了 Formatter 接口,它将被调用。Formatter 提供对格式的精细控制。
如果 %v 动词与 # 标志 (%#v) 一起使用并且操作数实现了 GoStringer 接口,则将调用该接口。
如果格式(对于 Println 等隐式为 %v)对字符串有效(%s %q %v %x %X),则以下两条规则适用:
如果操作数实现了错误接口,则将调用 Error 方法将对象转换为字符串,然后根据动词(如果有)的要求对其进行格式化。
如果操作数实现方法 String() string,则将调用该方法将对象转换为字符串,然后将根据动词(如果有)的要求对其进行格式化。
总而言之,这些fmt.*f功能将:
Format()方法,如果它存在,他们就会调用它。Error()方法,如果它存在,他们就会调用它。String()方法,如果它存在,就调用它。所以在实践中,这意味着%s和%v是相同的,除非Format()错误类型上存在方法(或错误是nil)。当错误确实有Format()方法时,人们可能希望它会产生与%s,%v和相同的输出err.Error(),但由于这取决于错误的实现,因此没有保证,因此这里没有“正确答案”。
最后,如果您的错误类型支持%+v动词变体,那么您当然需要使用它,如果您需要详细的输出。
nil 价值观虽然这是罕见的(故意)调用fmt.*f上的nil错误,行为确有不同之间%s和%v:
%s: %!s(<nil>)
%v: <nil>
Run Code Online (Sandbox Code Playgroud)
用于%v错误值。
if err != nil {
return fmt.Errorf("pack %v: %v", name, err)
}
Run Code Online (Sandbox Code Playgroud)
但是, In Go 1.13,该fmt.Errorf函数支持新%w动词。当这个动词存在时,返回的错误fmt.Errorf将有一个Unwrap返回参数的方法%w,这一定是一个错误。在所有其他方面,%w与 相同%v。
if err != nil {
// Return an error which unwraps to err.
return fmt.Errorf("pack %v: %w", name, err)
}
Run Code Online (Sandbox Code Playgroud)
需要区分%w和的地方%v:
阅读代码块中的注释
f, err := os.Open(filename)
if err != nil {
// The *os.PathError returned by os.Open is an internal detail.
// To avoid exposing it to the caller, repackage it as a new
// error with the same text.
//
//
// We use the %v formatting verb, since
// %w would permit the caller to unwrap the original *os.PathError.
return fmt.Errorf("%v", err)
}
Run Code Online (Sandbox Code Playgroud)
此外,内置的错误接口允许 Go 程序员添加他们想要的任何信息。它所需要的只是一个实现Error方法的类型
例子:
type QueryError struct {
Query string
Err error
}
func (e *QueryError) Error() string { return e.Query + ": " + e.Err.Error() }
Run Code Online (Sandbox Code Playgroud)
因此,大多数示例都有类似的实现类型,其中err有一个Error返回的方法string可供您使用%s
| 归档时间: |
|
| 查看次数: |
1719 次 |
| 最近记录: |