4 ms·
This higlights a point why I actually prefer exceptions to manually passing around error codes. If any of these calls to panic() are inside libraries, by using
by pilif 12y ago
This higlights a point why I actually prefer exceptions to manually passing around error codes.
If any of these calls to panic() are inside libraries, by using that library, you will put yourself into a position where your application will exit without giving you any recourse to fix it.
I've seen too many C libraries doing this too - "mmh - I can't handle this right now - let me just call exit()" (last time this happened was inside a commerical library for reading excel files. If it was confronted with a file that was corrupt in some way, the library would call exit(), terminating my application server in the process. Thanks)
With exceptions, a library can just throw but I as a consumer of the library at least get a chance to handle the error somehow and who knows - I might be able to find some way to still proceed and not crash.
If I don't handle that exception, oh well, then I crash anyways, but that's not different from the library calling exit or panic.
With exceptions, I also never risk that I (or a library I use) forgets to check for an exit code and proceeds to corrupt data (or crash way later at a seemingly unrelated point).
When I fail to catch an exception, I my application dies.
When I fail to check an error code, my application might possibly corrupt data.
Just because implementing exceptions in compiled languages is difficult and messy (C++) and because exceptions are slow doesn't mean we shouldn't be using them. It means that we have to improve our language and OSes in order for them to work without hacks and quickly enough because, honestly, the value they provide to me is big enough to warrant a bit of research.
- Tobani 12y agoPanic is not exit. http://golang.org/pkg/os/#Exit http://golang.org/pkg/os/#Exit is exit Panic is throw. Recover is an isomorphism for catch. For the most part. You have to explicitly ignore error codes in go. (Not that you can't handle them incorrectly.)
- NateDad 12y ago"In order to ignore error codes in go, you must do so explicitly". - FTFY
- Tobani 12y agoYeah. The only caveat I'd give is a bit of a stretch. Not explicitly error handling, but you can lookup maps as: j := m["root"] or j, ok := m["root"] Again, this tangential to the subject at hand. But this is the main reason I qualify that statement.
- NateDad 12y agoThat's a very good point, actually. It's tricky, because always requiring the latter format is burdensome, especially if the zero value of the map is an ok value for you...
- robryk 12y ago> You have to explicitly ignore error codes in go. (Not that you can't handle them incorrectly.) I'm not sure I udnerstand what you mean. I can write: fmt.Fprint(os.Stdout, "Something\n") This returns an error, which I silently discard. Did you mean something else?
- Tobani 12y agofmt.Fprint(os.Stdout, "Something\n") By itself isn't a valid statement. You try to compile that and you'll get an error saying unused return value. So you'll try: err := fmt.Fprint(os.Stdout, "Something\n") and you could ignore err, but then you'll get a compiler saying err is defined but never used. So you can be like NAH I'm just trying to muck stuff up so I"m going to do this. _ = fmt.Fprint(os.Stdout, "Something\n") Which is explicitly discarding the error much like: try{ fmt.Fprint(os.Stdout, "Something\n") }catch(Throwable t){}
- robryk 12y agoI'm sorry, but that's not true: http://play.golang.org/p/PiMXQkKOef http://play.golang.org/p/PiMXQkKOef
- Tobani 12y agoSo it appears you're right. For things for which you don't care about any value returned this is the case. The reason I haven't run into this is for the most part things that can error, they also return a value that matters. You can't use the return value without doing something with the error. http://play.golang.org/p/yreUbxx5Vv http://play.golang.org/p/yreUbxx5Vv So it appears that there is a loophole for things that can error and purely used for side effects.
- NateDad 12y agoThis is true, you can drop all return values. However, a lot of functions return a value and an error. If you want to access the value, you need to assign the error to something too. And if you don't then use that error, the compiler will complain about it. For simply dropping all return values on the ground, there are linters that will complain for you: https://github.com/kisielk/errcheck https://github.com/kisielk/errcheck
- NateDad 12y agoSo, as others said, panic is very similar to throw, it's just intentionally ugly and strongly discouraged. There are linters which will tell you when you forget to check an error code. You say that unhandled errors can cause data corruption, but what about improperly cleaning up resources? That happens all the time... you have your data partially written to disk and something throws an exception, if you don't have your cleanup code in a try/finally, then bam, corrupt data. That's a lot more likely with the mindset of generally just letting exceptions fly.
- WorldWideWayne 12y ago>> but what about improperly cleaning up resources? What about it? Are you saying that error return values somehow force programmers to properly cleanup resources? >> That happens all the time... How are you quantifying that? I write code in exception bearing languages all the time and never have this problem. Why would you begin a partial write and then call some code that would likely produce errors or exceptions? That sounds like a recipe for corrupt data no matter the style of error catching. A better way would be to use a method of writing that is basically atomic. A lot of your arguments in this thread sound a bit contrived.
- NateDad 12y agoI'm saying that most people who complain about Go's verbosity do not take resource cleanup into consideration. They think they can let exceptions fly without any try/catch or try/finally and everything will be fine, which is obviously untrue. Sorry, what I meant by "happens all the time" is that there are often cases where you need cleanup code that gets called if the function doesn't exit cleanly. There's very often no atomic way to perform a series of actions. Please keep in mind, I was being very vague on purpose. There is almost always a list of actions that you want to either all succeed, or else you need to do some cleanup if later ones fail. In code with exceptions, you don't always know what can throw. Unless you're using java code that has been written with strict checked exceptions, you have to assume any external function you call can throw. Even if it doesn't now, it might when Bob from the next team over decides that now it should. I really don't think it's at all contrived. I'm not saying you can't write this code with exceptions, I'm saying it's harder than it needs to be, and it's at least as verbose as Go, if you're doing all the right things with your try/catch/finally's.