4 ms·
Is there a link to this discussion? This seems interesting. If I can’t make a call to a downstream service, or a file I’m trying to read doesn’t exist, or a s3
by anthlax 4y ago
Is there a link to this discussion? This seems interesting. If I can’t make a call to a downstream service, or a file I’m trying to read doesn’t exist, or a s3 bucket 404’s, or almost any other “real world” error I can think of, the only (sane) way I can think of handling this is propagating the error down to the caller (and perhaps logging?)
Do you mean to say that it is idiomatic in Go to handle errors by… doing something else?
On mobile so I can’t put in a code block, but here’s how I thought Go was written:
value, err := some_fn()
If err != nil { Return err }
(? Operator works here because you could do value := some_fn()? And remove the if statement boilerplate)
Do you mean that instead of “return err” Go idiomatically does something else?
- randomdata 4y ago> the only (sane) way I can think of handling this is propagating the error down to the caller A big problem, among many, with doing that is that you leak implementation details out of the abstraction. If, to stick with your example, you have a function that helps you with reading files, the caller shouldn't care where the data is stored. Today it might be the local filesystem, tomorrow S3, and when you make that change nothing about the rest of the program should break. But you can't count on the lower level functions using the same errors. As you suggest, a "a file I’m trying to read doesn’t exist" isn't represented as a "bucket 404", even though at a higher level they are the exact same thing. If you straight returned the "a file I’m trying to read doesn’t exist" error as you got it from the file API, now the caller is going to depend on that, and when you replace it with the S3 function that returns a "bucket 404" error, everything starts to break. What you typically want to do is return a more generalized "not found" error that can remain stable regardless of specific implementation details. There are rare cases where you can get away with simply returning the value up the stack, but in the majority of cases you need to handle the error, either by doing something with it or returning a new error that is more useful to the caller. And, so, try becomes essentially unusable without the language taking a larger macro take on supporting such a feature. Like the sibling comment points out, Rust does "from" conversion when using try (?) to try and avoid encountering the same fate.
- still_grokking 4y ago> A big problem, among many, with doing that is that you leak implementation details out of the abstraction. If, to stick with your example, you have a function that helps you with reading files, the caller shouldn't care where the data is stored. Today it might be the local filesystem, tomorrow S3, and when you make that change nothing about the rest of the program should break. This would lead to the situation where a local call is treated as the same thing to a network call. Which is know to be a very bad design. > Like the sibling comment points out, Rust does "from" conversion when using try (?) to try and avoid encountering the same fate. Yeah, and it avoids all the hassle. Why couldn't any language (and especially Go) just do the same?
- randomdata 4y ago> Which is know to be a very bad design. If your abstraction leaks that the implementation is a local call, and then you try and change that later, unquestionably. Again, you need to avoid leaking implementation details, which is too why you can't just add a try operator and make it automatically useful. Any leak of any kind in your abstraction will make life miserable later. Don't let your abstraction leak. > Yeah, and it avoids all the hassle. All it does is move where the code is located, placing the onus on the producer "the producer is always right" instead of the caller "the customer is always right". You don't actually avoid anything, just change the perspective. > Why couldn't any language (and especially Go) just do the same? Perhaps it could, but it requires that the language take a more macro look at the problem. It is not a microfeature.
- deleted 4y ago[deleted]