Given this, I don't see how Go is any worse with respect to sloppy programmers. They'll Always Find A Way.
Also, why couldn't your second example be nested? It seems like either of those two examples could be structured identically to the other.
Given this, I don't see how Go is any worse with respect to sloppy programmers. They'll Always Find A Way.
Also, why couldn't your second example be nested? It seems like either of those two examples could be structured identically to the other.
Errors should never pass silently
Unless explicitly silenced
The problem with go is that you have 3 error modes:1. Explicitly handle everything
2. Implicitly silence sometimes
3. Panic/recover explodes sometimes (who knows where/when?)
Mode #2 is dangerous.
Java/Python give you 2 only modes:
1. Implicitly explode on error.
2. Explicitly silence sometimes.
Where both modes aren't inherently dangerous, i.e. they won't directly cause undefined states to execute.
--------------------
Concerning the nesting in my examples - I'm used to the style of C programming where failing is mostly handled by a return as to keep the program as readable (and thus flat) as possible. So pardon my french but I assumed "// do something" would somehow prevent further usage of 'f'.
Note that the Go example, although tedious, isn't bad in cases where you really do need to check every single possible error.
You could certainly argue for handling each message in a separate process a la erlang, but this approach worked well for us.
I think checked exceptions were a mistake (IIRC Gosling agrees), and Java could do with better support for multiple return values (which exceptions get abused for), but I like Java-style runtime exceptions.
I'm pretty sure you wouldn't do that. You'd have a shallow tree of processes, each leaf process would be tasked with doing message processing e.g. provided by its supervisor. The supervisor would "manage the queue" so to speak, and depending on the semantics of the queue it would have 1 to n children; and it would be tasked with marking failed messages when a child process would blow up (and restarting a new child).
Modelling messages as processes would likely be impractical.