Skip to content

Instantly share code, notes, and snippets.

What would you like to do?

EDIT: On further thought, the implications of using iface.As, e.g., for io.WriterTo are quite subtle. If you were trying, say, to add logging to all Read calls, you wouldn't want to simply pass through to the underlying io.WriterTo because the call would go unlogged. Instead you'd need to implement the As method on your type so as to only return a WriterTo under certain conditions. Still, I think this idea is worth exploring more.

The Go 2 process has produced a proposal for extending the errors standard package, which is currently in testing.

My observation about the experimental errors package is: As() and Is() solve problems that exist well beyond the error interface.

Essentially the problem is this, many packages begin by requiring a certain interface, such as error, io.Reader, or http.ResponseWriter. In time, it becomes clear that the packages can be further extended by creating specialized variants that are available as optional interfaces, such as io.WriterTo or http.Pusher. You can test for them by doing v, ok := i.(OptionalInterface) These optional interfaces preserve backwards compatibility while adding new capabilities. There is a cost, however. Using an optional interface makes wrapping an interface value very difficult. If, for example, I make an http.Handler middleware that replaces the ResponseWriter so that I can record responses, it is a lot of work to make this also conform to http.Pusher, but only when the underlying connection actually supports it.

As and Is provide a solution to this problem for optional interfaces of error values, but there's no reason this couldn't be used for other optional interfaces. I proposes that As, Is, Wrapper, Unwrap, and Opaque be moved into a package called iface and made to work with interface{} instead of error and the standard library should use iface.As in place of existing optional interface tests.

You can’t perform that action at this time.