go-errors icon indicating copy to clipboard operation
go-errors copied to clipboard

[Proposal] No way to check the cause if using a mix of go-errors and standard errors

Open erizocosmico opened this issue 6 years ago • 7 comments
trafficstars

Let's imagine we are using a mix of this library and standard errors created with errors.New or fmt.Errorf.

Consider the following snippet:


var errStd = stderrors.New("something")

var errKind = errors.NewKind("something: %s")

var myErr = errKind.Wrap(errStd, "foo")

If we want to check if myErr has errStd as its cause, we need to do the following:

 err, ok := myErr.(*errors.Error)
if !ok {
  // handle
}
if err.Cause() == errStd {
}

This is potentially more cumbersome if the original error is deeply nested. Perhaps we could have a function IsCausedBy(err, cause).

In this case, it would become:

if errors.Is(myErr, errStd) {
  // do something
}

Implementation could look like this:

func Is(err, cause error) bool {
    e, ok := err.(*Error)
    if !ok {
        return false
    }
    
    if e, ok := e.cause.(*Error); ok {
        return Is(e, cause)
    }

    return e.cause == cause
}

erizocosmico avatar Aug 02 '19 12:08 erizocosmico

This looks very similar to the semantics of the current error inspection proposal implemented by https://godoc.org/golang.org/x/xerrors.

creachadair avatar Aug 02 '19 19:08 creachadair

Yup, this and the other proposal are basically bringing the good bits of xerrors to go-errors so the library it’s more stderror friendly On 2 Aug 2019, 21:04 +0200, M. J. Fromberger [email protected], wrote:

This looks very similar to the semantics of the current error inspection proposal implemented by https://godoc.org/golang.org/x/xerrors. — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or mute the thread.

erizocosmico avatar Aug 02 '19 19:08 erizocosmico

Yup, this and the other proposal are basically bringing the good bits of xerrors to go-errors so the library it’s more stderror friendly

That makes sense. But I wonder if it's possible to do so by integrating with the Wrapper API so that (say) xerrors.Is and xerrors.As would work without needing a new helper?

creachadair avatar Aug 02 '19 20:08 creachadair

Yeah, implementing Wrapper would be nice as well, but for a go-errors user, the point of using the library is not needing to use errors (xerrors in this case), so that all you need to handle errors is in there. If we were to only implement Wrapper you'd need to also import xerrors (or errors when it's merged into the stdlib) for that specific use case. We can have the implementation of Wrapper to make go-errors errors usable with xerrors, but I'd still suggest adding a helper here.

erizocosmico avatar Aug 02 '19 21:08 erizocosmico

We can have the implementation of Wrapper to make go-errors errors usable with xerrors, but I'd still suggest adding a helper here.

That makes sense. You might consider using the same name, though, so that errors.Is maps to the semantics of xerrors.Is.

creachadair avatar Aug 02 '19 22:08 creachadair

By the way, the standard library already has an errors package, that most non-trivial Go programs already use (it's the origin of errors.New for example). At source{d} we mostly do not use the stdlib errors directly, but it's very common in most Go codebases. So if/when the xerrors proposal gets integrated, it shouldn't add any build mass to the packages that use it. (That doesn't affect this package directly, though)

creachadair avatar Aug 02 '19 22:08 creachadair

That makes sense. You might consider using the same name, though, so that errors.Is maps to the semantics of xerrors.Is.

Fair enough.

So if/when the xerrors proposal gets integrated, it shouldn't add any build mass to the packages that use it.

It wasn't because of adding size to the binary. It was because when using go-errors, one should not need to use any other library for error handling, since all needed features are expected to be provided by the library.

erizocosmico avatar Aug 05 '19 07:08 erizocosmico