|
|
|
|
|
by morelisp
1466 days ago
|
|
As I already mentioned - Go has largely unbounded error types, not because `error` is a small interface, but because of how many interfaces get nested (a tar.Writer wrapping a gzip.Writer wrapping an hdfs.Writer etc.). If you don't like this, fine, we'll have to agree to disagree about the value of checked exceptions vs. massively leaking implementation details. Nonetheless, Go does provide ways to check whether an error either is or can do what you want, and ways to annotate errors with logic specific to your program. An `httpClientError` is an `error`. When you get an error from a source you want to treat as a 400, you wrap it and return it, as an `error`. You use `errors.As` on it as a concrete type, or an `interface { HTTPStatus() int }`, to use the method you've added. Regarding localization, which is a significantly different problem - the outcome is e.g. "file can't be opened". It's hard to write good error messages based on the language's error messages but this is not a Go-specific problem at all. Either you constrain your operations to the point you can bound all your error types, or you don't and report the outcome + raw message instead of trying to localize causes. And yes, this is an unusual space to be using Go or Java. Since you mentioned Rust, we could also consider how it solves the problem - `Write` returns a `Result<usize, io::Error>` - `io::Error` has a (almost uselessly long and yet still) non-exhaustive `ErrorKind` - the last of which is `Other`, "used to construct your own Errors that do not match any ErrorKind." I.e. even in Rust's type system, they punted because otherwise you can't easily compose anything. |
|