%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)
我是否应该优先选择另一个?
最佳答案
Should I use %s or %v to format errors?
TL; DR; 都没有。在99.99%的情况下使用
%w
。在其他0.001%的情况下,%v
和%s
可能“应该”具有相同的行为,除非错误值是nil
,但不能保证。对于%v
错误,nil
的友好输出可能是偏爱%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
呢?in the docs提供了有关如何实现
%s
和%v
的详细信息。我已经强调了与您的问题有关的部分。
If the operand is a reflect.Value, the operand is replaced by the concrete value that it holds, and printing continues with the next rule.
If an operand implements the Formatter interface, it will be invoked. Formatter provides fine control of formatting.
If the %v verb is used with the # flag (%#v) and the operand implements the GoStringer interface, that will be invoked.
If the format (which is implicitly %v for Println etc.) is valid for a string (%s %q %v %x %X), the following two rules apply:
If an operand implements the error interface, the Error method will be invoked to convert the object to a string, which will then be formatted as required by the verb (if any).
If an operand implements method String() string, that method will be invoked to convert the object to a string, which will then be formatted as required by the verb (if any).
总而言之,
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>
Playground link
关于string - 我应该使用%s还是%v格式化错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61283248/