3 ms·
See Dave's previous post on this: "Don’t just check errors, handle them gracefully" [0] Here he explores the various possible implementations and their problems
by infogulch 10y ago
See Dave's previous post on this: "Don’t just check errors, handle them gracefully" [0] Here he explores the various possible implementations and their problems then introduces a good solution. In short:
1. Assert error behavior not type or message, i.e. the error has a specific method. NOT `type HTTPError struct {Message string;Code int;}` but instead `type HTTPError interface {error;HTTPCode() int;}`. This decouples the location and specific implementation of the error type from the extra information you're adding to it.
(Corollary: Interfaces are Go's only real way to create custom generics. You'll be much happier if you can map your problem space onto interfaces.)
2. Number 1 doesn't help when you wrap errors, because the wrapping error hides any methods on the original. Dave's errors package helps with errors.Cause() that exposes the original error so you can apply #1 effectively.
[0]: http://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully http://dave.cheney.net/2016/04/27/dont-just-check-errors-han...
- fauigerzigerk 10y agoAgain, I have read Dave Cheney's posts, and I totally agree with his conclusion that sentinel errors (i.e. public package level singletons) should not be used. I don't necessarily agree with his stance on error types, because sometimes we need access to specific data attached to errors (e.g SQLSTATE). But the standard library uses sentinel errors everywhere and third party packages often do the same. That's what creates the inconsistent and messy status quo of handling different types of errors. It's also not going to change because sentinel errors can never be changed into anything different without breaking clients of the API. No call specific message or other data will ever be added to these standard error values.
- infogulch 10y ago> sometimes we need access to specific data attached to errors (e.g SQLSTATE). Dave's post and my entire comment directly address this: Add a `SQLCode() int` method to the custom error, return `error` type and users can assert `codeErr, ok := err.(interface{SQLCode() int}); code := codeErr.SQLCode();` somewhere up the stack to get it. But yes, the standard library's use of sentinel errors is unfortunate and can't be fixed.
- fauigerzigerk 10y ago>my entire comment directly address this You're, right. Sorry for that.