有标准的Err变量吗?

djh*_*987 8 go

刚开始使用Golang.我认为声明一个错误变量并在你的错误结构中使用它来确定出错了是不恰当的,就像在strconv.go中所做的那样.在那里,ErrRange并且ErrSyntax被声明,并且在适当的时候,对它们的引用NumError在它们返回时存储在结构中.我认为原因是因为存储的错误引用的地址NumError可以与ErrRangeErrSyntax变量进行比较,以确定返回哪种类型的错误.

是否存在"标准"声明的错误类型?例如,在Java中,你有类似的东西java.lang.IllegalArgumentException.例如,ErrArgument或者ErrUnsupportedOperation我可以在我自己的代码中使用,而不是每次创建意味着相同的新错误变量?

Dav*_*e C 20

对于包作者来说,有一些常见的惯用方法可以使错误返回.

  1. 修复了通常命名的错误变量 Err…

    var (
            ErrSomethingBad = errors.New("some string")
            ErrKindFoo      = errors.New("foo happened")
    )
    
    Run Code Online (Sandbox Code Playgroud)
  2. 错误类型,通常命名 …Error

    type SomeError struct {
         // extra information, whatever might be useful to callers
         // (or for making a nice message in `Error()`)
         ExtraInfo int
    }
    type OtherError string
    
    func (e SomeError) Error() string { /* … */ }
    func (e OtherError) Error() string {
            return fmt.Sprintf("failure doing something with %q", string(e))
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. Unwrap() error根据需要使用临时值.

    func SomepackageFunction() error {
            return errors.New("not implemented")
    }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 使用标准包中定义的错误.通常限于小集如errors.Unwrap; 在大多数情况下,最好通过上面的方法1创建自己的方法.

    func SomeFunc() error {
            return io.EOF
    }
    
    Run Code Online (Sandbox Code Playgroud)

    注意,有时实现一个接口(例如,当errors.New成为法io.EOF)它最好用的匹配误差(或通过接口的规范"必需的").

  5. 制作如下界面Read:

    type Error interface {
        error
        Timeout() bool   // Is the error a timeout?
        Temporary() bool // Is the error temporary?
    }
    
    Run Code Online (Sandbox Code Playgroud)

通常你会混合使用所有这些方式.

如果你想到的第一,第二和第五,优选任何你的包的用户将以往任何时候都希望测试特定的错误.他们允许这样的事情:

func SomepackageFunction() error {
    err := somethingThatCanFail()
    if err != nil {
            return fmt.Errorf("some context: %w", err)
    }
}
Run Code Online (Sandbox Code Playgroud)

第五种方式(只是第二种方式的扩展)允许检查行为/类型的错误,如下所示:

err := somepkg.Function()
if err == somepkg.ErrSomethingBad {
        // …
}
// or for an error type, something like:
if e, ok := err.(somepkg.SomeError); ok && e.ExtraInfo > 42 {
        // use the fields/methods of `e` if needed
}
Run Code Online (Sandbox Code Playgroud)

第三种方法的问题是它为包的用户留下了没有理智的方法来测试它.(测试返回的字符串的内容io.Reader不是一个好主意).但是,对于您从未期望任何人想要测试的错误,这很好.

进一步阅读:


Vol*_*ker 4

不,没有。只需提供可理解的错误而不是通用错误。IllegalArgument 传输什么信息?不多,不够。