string - 我应该使用%s还是%v格式化错误

标签 string go error-handling formatting

%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.Iserrors.As一起考虑。 。

唯一不适合的时间:
  • 您必须支持Go的较旧版本,并且xerrors不是一个选择。
  • 您想创建一个唯一的错误,而不是包装现有错误。例如,如果您在搜索用户时从数据库中收到Not found错误,并且想要将此错误转换为Unauthorized响应,则这可能是适当的。在这种情况下,很少会在任何格式化动词上使用原始错误值。

  • 好吧,那么%v%s呢?

    in the docs提供了有关如何实现%s%v的详细信息。我已经强调了与您的问题有关的部分。

    1. 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.

    2. If an operand implements the Formatter interface, it will be invoked. Formatter provides fine control of formatting.

    3. 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:

    4. 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).

    5. 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%verr.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/

    相关文章:

    java - 从字符串数组中提取标记位置 - Java

    excel - Excel 是否有 "On Alert"的 VBA 和 "On Error"一样?

    c# - Log4Net错误: “Failed to find configuration section log4net” AdoNetAppender

    Golang 类型转换

    validation - 如何添加开始日期和结束日期的开始验证?

    php - golang S3 客户端库是否具有获取 Iterator 函数来检索 S3 存储桶中的所有对象

    python - 我的函数使用 'None'返回了新行

    python - .join() 在 python 中给出返回列表

    python - 如何用python分割这个字符串?

    iOS:自增 NSString