4 ms·
The problem isn't the methodology. Its the library support. I (for my employee) wrote a library a few years ago (~go 1.1) with "errs.New" and "errs.Append(err,
by voidlogic 10y ago
The problem isn't the methodology. Its the library support. I (for my employee) wrote a library a few years ago (~go 1.1) with "errs.New" and "errs.Append(err, ..work like fmt..)" that generates error that look like:
main.go:13 main.main(): highest level error;
Details: foo.go:8 foo.ExportedMethod(): mid level error;
Details: foo.go:42 foo.innerMethod(): low level error!
It provides handy helpers like GetRootErr and PanicToError too. I hope we can opensource it in the next month or two.
- notheguyouthink 10y agoYup, my solution as well. As well as a couple other common libraries (eg: https://github.com/pkg/errors https://github.com/pkg/errors) The only downside to this is you can no longer treat errors as values. Eg, you can't do: err := Func() if err == ErrBadThing { // do stuff } So you have to implement some type of `Cause()` method. In my lib, i have `errors.Cause()` which returns the root error, as well as a shorthand func `errors.Equals(err, ErrBadThing`)`
- lobster_johnson 10y agoThere's already a good library like that: https://github.com/pkg/errors https://github.com/pkg/errors It is API-compatible with the errors package, and you get errors.Wrap(err, message), errors.Wrapf(err, message, args) and errors.Cause(err).
- voidlogic 10y agoWe wrote ours around the time Go 1.1 was released so its way older and featureful than that package.
- kodablah 10y agoIt's not that it can't be done, it's that it's not in the stdlib. Without being in the stdlib, each set of code solves the same problem in its own way harming conformity. It's gotten so bad that some libs include stack traces and some even parse panics. For example, how do I write a function that loops over the error chain if it may have come from several libs with different impls? The problem is they shot themselves in the foot and may have to incorporate a form of "default" method to get around it like Java ended up having to. You can't have a "ContextualError" type because what does "Cause()" return? If it returns "errors.Error" then you require users to use a type assertion. If it returns "ContextualError" then it can't chain existing errors without wrapping. They also can't add anything to the "errors.Error" interface because they would invalidate all existing impls of that interface.
- Groxx 10y agoPython suffers immensely from this - libraries tend to reraise exceptions with a new, descriptive type, but usually don't append the stack, and essentially can't chain any custom data you may have added. Not having the complete causal chain can seriously hamper debugging, and unless it's built in it's unlikely to be adopted consistently. Python 2 has nothing, and libraries haven't agreed on anything. Python 3 has "raise ... from ...", which largely resolves it, but I'm not sure what adoption is like. Anyone know?