String 我应该使用%s或%v格式化错误吗
String 我应该使用%s或%v格式化错误吗,string,go,error-handling,formatting,String,Go,Error Handling,Formatting,%s和%v都可以用来格式化Go中的错误,而且似乎没有功能上的区别,至少表面上是这样 我们在Go自己的工具中看到了这两者 在: 返回fmt.Errorf(“格式错误的导入路径%q:%v”,路径,错误) 在: base.Fatalf(“%s”,err) 我应该更喜欢其中一个吗?使用%v作为错误值 如果出错!=零{ 返回fmt.Errorf(“包%v:%v”,名称,错误) } 但是,在Go 1.13中,fmt.Errorf函数支持一个新的%w动词。当存在此谓词时,fmt.Errorf返回的错误将有一
%s
和%v
都可以用来格式化Go中的错误,而且似乎没有功能上的区别,至少表面上是这样
我们在Go自己的工具中看到了这两者
在:
返回fmt.Errorf(“格式错误的导入路径%q:%v”,路径,错误)
在:
base.Fatalf(“%s”,err)
我应该更喜欢其中一个吗?使用
%v
作为错误值
如果出错!=零{
返回fmt.Errorf(“包%v:%v”,名称,错误)
}
但是,在Go 1.13
中,fmt.Errorf
函数支持一个新的%w
动词。当存在此谓词时,fmt.Errorf
返回的错误将有一个Unwrap
方法返回%w
的参数,该参数必须为错误。在所有其他方面,%w
与%v
相同
如果出错!=零{
//返回一个展开为err的错误。
返回fmt.Errorf(“包%v:%w”,名称,错误)
}
需要区分%w
和%v
的位置:
%s: %!s(<nil>)
%v: <nil>
阅读代码块中的注释
f,err:=os.Open(文件名)
如果出错!=零{
//os.Open返回的*os.PathError是一个内部详细信息。
//为了避免将其暴露给调用者,请将其重新打包为新文件
//相同文本的错误。
//
//
//我们使用%v格式动词,因为
//%w将允许调用方打开原始*os.PathError。
返回fmt.Errorf(“%v”,err)
}
阅读:
此外,内置的错误接口允许Go程序员添加他们想要的任何信息。它只需要一个实现
Error
方法的类型
例如:
type QueryError struct {
Query string
Err error
}
func (e *QueryError) Error() string { return e.Query + ": " + e.Err.Error() }
因此,大多数示例都有类似的实现类型,其中err
有一个Error
方法,该方法返回string
,您可以使用%s
我应该使用%s或%v格式化错误吗
TL;博士都不是。在99.99%的情况下使用%w
。在其他0.001%的情况下,%v
和%s
可能“应该”表现相同,除非错误值为nil
,但没有保证。对于nil
错误,%v
的友好输出可能是首选%v
的原因(见下文)
详情如下:
使用%w
而不是%v
或%s
:
从Go 1.13(或更早版本,如果您使用的话)开始,您可以使用%w
动词,仅用于错误
值,该动词包装错误,以便以后可以使用展开,并且可以考虑使用和
唯一不合适的情况是:
xerrors
未找到
错误,并希望将其转换为未经授权的
响应,则这可能是合适的。在这种情况下,很少会将原始错误值与任何格式动词一起使用%v
和%s
呢?
有关如何实现%s
和%v
的详细信息可用。我已经强调了与你的问题相关的部分
fmt.*f
功能将:
Format()
方法,如果它存在,他们将调用它Error()
方法,如果它存在,他们将调用它String()
方法,如果它存在,则调用它%s
和%v
是相同的,除非错误类型上存在格式()
方法(或者错误为nil
)。当一个错误确实有一个Format()
方法时,人们可能希望它将产生与%s
、%v
和err.error()
相同的输出,但由于这取决于错误的实现,因此没有保证,因此这里没有“正确答案”
最后,如果您的错误类型支持%+v
动词变体,那么您当然需要使用它,如果您需要详细的输出
nil
值
虽然很少(故意)在出现nil
错误时调用fmt.*f
,但%s
和%v
之间的行为确实不同:
%s: %!s(<nil>)
%v: <nil>
%s:%!s()
%五: