Skip to content

all: updating existing errors to work with the Go 1.13 error values #30322

@jimmyfrasche

Description

@jimmyfrasche

This issue is for discussing how to update errors in the standard library and golang.org/x packages to work with the Go 2 error values changes proposed in #29934.

That issue is for discussing the proposal itself. This is for discussing how best to update existing error types to make the most use of the new additions to the errors package, assuming that it is accepted.

All calls to errors.New will be updated automatically.

All calls to fmt.Errorf that do not wrap errors will be updated automatically. Those that wrap errors will not be.

No custom types, outside of the errors package itself, will be updated automatically.

How will the errors that would require manual updating be updated?

For fmt.Errorf the only question is whether to turn a %s/%v to a %w.

For custom types, the questions are

  • should they have an Unwrap method?
  • should they collect stack frames?
  • should they have a FormatError method?
  • Do any require an Is method?
  • An As Method?

If one of the above obviates an older approach (like an Err error field on a struct) should the older approach be marked deprecated?

Even with a general policy, there will likely be exceptions.

net.Error's extra methods vs os.IsTimeout and co. is a particular wrinkle.

The os.IsX predicates test the underlying error of a finite set of error types for certain (platform specific) error values. This does not work with arbitrarily wrapped errors. @neild's https://golang.org/cl/163058 contains a proof-of-concept for changing it so that one can write the more general errors.Is(err, os.ErrTimeout) instead of os.IsTimeout(err).

The predicate methods defined in net.Error offer a similar approach. In the case of IsTimeout, overlapping. To test a general error for this method you can write

var timeout interface { IsTimeout() bool }
if errors.As(err, &timeout) && timeout.IsTimeout() { //etc.

This is slightly more verbose than the Is construct.

Adding an Is method to net.Errors that respond to ErrTimeout and an ErrTemporary could make it more like os. Adding predicate methods to the os errors could make them more like net. Ideally they would be the same because if they're wrapped in further errors the code inspecting them may not know which package the original comes from and would have to handle both.

The approaches are not equivalent when there are multiple errors in the chain that can have the same property. Say error A wraps error B and either may be temporary but only B is. The As construct sets timeout to A whose method returns false (unless it inspects the chain on its own) but the Is construct returns true. If the intent is to override the temporary-ness of B an Is method on A that returns false for ErrTemporary is easy enough. It seems both more flexible and concise.

Metadata

Metadata

Assignees

No one assigned

    Labels

    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions