4 ms·
That's what I though, since in Go you also need to declare your error struct and implement the error interface on it.
by arthursilva 12y ago
That's what I though, since in Go you also need to declare your error struct and implement the error interface on it.
- jerf 12y agoWhich is not something you generally do a lot of. Most functions either pass an error through or simply return a string error through errors.New(). (That's often not a cheat, either; my modules tend to declare the set of errors as globally-exported variables, allowing you to use == to figure out which error you're getting if you care. If your errors don't take parameters that works fine.) And the error interface only has one method instead of three. Less boilerplate in the worst and the common cases, less compile time guarantees. It is debatable whether passing errors through is a good idea in theory or in practice at scale (two separate questions there). So far it hasn't bit me at all, though, and I've got a good idea of what I'm looking for for such "bitings". I find in practice there's two types of errors: Errors I know how to do something about, and errors I don't. In the first case, I can only be dealing with a certain restricted set of errors coming back and I must inevitably write special-purpose code for the given error, and in the second, I don't much care about what it is so I often send it along untouched. I haven't found anything that manages to split the difference yet. Even returning a wrapped error is rare in my application code, though it has its place in library code. I'm also finding in my real code that the ratio turns out to be closer to 1:2 errors I can do something with/errors I can't, which makes the explicit handling not matter so much. (My gut feeling is that if you find you are always just "return err"ering, and especially if you are doing it without thought, you're writing code that is passing up on some robustness.)
- NateDad 12y agoYeah, I agree about wrapping. I actually usually try to avoid just doing return err, because you're losing some context that this code understands that the below code doesn't.... like if you return a FileNotFound error, the caller might not know why you were looking for that file, so you should wrap it and say fmt.Errorf("couldn't find config file: %s", err), that way if the user sees the error message, he'll see "couldn't find config file: open: file not found: foo.yml" instead of just "open: file not found: foo.yml".
- jerf 12y agoFlatting the error to a string isn't a good idea, unless you're sure you're dumping it straight out to the user (and by that I mean literal human, not merely "caller"). If you're returning it from a function, you need to wrap it, as in the Rust examples, so the caller can extract the original if they want to do something about it.
- mercurial 12y agoLike localizing it, for instance. Having a message is fine, having weakly-typed errors in production-quality code isn't.
- NateDad 12y agoWell, so there's two theories there... there's the theory you're saying, that the caller might want to know it's a filenotfound, and handle it programmatically... and there's the theory that the fact that you're doing file I/O is an implementation detail that callers shouldn't depend on, because it could change. What side of that argument you fall on depends a lot on the specifics of your code, and how much you want to sanitize your errors (and how likely you think callers will actually be able to do something programmatically about an error). I agree with both sides, and what I do in any particular situation depends a lot of on the details of what I'm doing.
- jerf 12y agoNo, this doesn't fit either case. If you are going to return the error details in a way the human user can read, then you really ought to just return them symbolically, because a programmer will start running regexes over your error codes to figure out what happened. If you're going to not show the underlying error, then either be willing to entirely hide it (sometimes appropriate, probably not for the usual IO case but there are internal errors for which a translation is appropriate) or wrap and pass up, but don't wrap and pass up as a string. That's the worst of all worlds.
- NateDad 12y ago