I'm enjoying using Go for the few small services I'm using it for but it seems that a language which has to constantly fight it's users to reinforce what it considers idiomatic has some core issues.
Python is another language where there is a lot of talk about idiomatic code ('Pythonic').
C++11 and C++14 also have a lot of idiomatic discussion since the community's trying to move to a different style with the latest enhancements.
Not sure if this is a signal of core issues.
I wonder what an appropriate adjective could be for idiomatic Go code. Gonic? Gonian?
I've grown to prefer it, as exception handling typically boils down to "not my problem" in most code bases. Go forces you to think through each error condition, which is an unusual amount of effort for people who may not be accustomed to it.
You need discussion about what's considered "good" before you can arrive at a relatively common opinion about that.
That said, I've tried channeling Rob and it is an interesting and informative experience ..
http://talks.golang.org/2014/readability.slide#11
In this example, have to check error 3 times to write 4 lines of code.
The function would be '... throws IOException'. That seems to satisfy the "think of disk/network failure as a very common case" design goal with minimal boilerplate. That brings up a separate discussion on checked vs unchecked exceptions, but I guess we can save that one for comparisons against a language with unchecked exceptions!
However, after a few months of writing code using that model, I find that I don't really like it and prefer the if err != nil model much more.
While this can appear to be a little tedious, I've found it extremely useful once I started checking code coverage in my tests. It makes it very clear which exceptional cases you aren't testing. This in turn makes it obvious how well tested the code is. I know from looking at my code coverage what kind failures I'm handling properly and which ones I'm delegating to the caller. This allows for better documentation where API users know what failure modes to expect.
[1] https://godoc.org/github.com/surullabs/fault [2] https://golang.org/doc/effective_go.html#recover
The biggest problem I have had most so far is when reading other code, finding the meaning amongst all of the error nil checks and the sprawling if conditions that they bring.
Another thing that makes it difficult is the preference for scattering returns everywhere and avoiding `else if`s, I read code structurally so code like this from slide 29 (http://talks.golang.org/2014/readability.slide#29) is really difficult to parse.
func finishStatus(r Result, complete bool) int {
if !complete {
return http.StatusAccepted
}
if stat, ok := r.Object.(*api.Status); ok && stat.Code != 0 {
return stat.Code
}
if r.Created {
return http.StatusCreated
}
return http.StatusOK
}When I see code like this I will assume that it's going to check every condition:
if !complete {
// do something
}
if stat, ok := r.Object.(*api.Status); ok && stat.Code != 0 {
// do something
}
if r.Created {
// do something
}
If the first condition matching causes the second, third, nth condition to not be checked then why not make it clear in the code by adding an `else`?The recommended way means that I can't trust my assumption and that I'll have to read the entire function and examine the `//do something`s instead
But then what would the following "if" look like ?
Simply spoken, the original code will suppress the error from out.Close().
I think this is tricky in any language.
Playing around a bit, I discovered that the arrow keys bring you to the next slides. Perhaps there could be a way to make that more obvious, or provide buttons onscreen.