
When in Go, do as Gophers do - jvermillard
http://talks.golang.org/2014/readability.slide#1
======
dyadic
I've only been using Go for less than a week and my impressions are less than
good. I'm still waiting and hoping to understand what it is that people like
about Go, but I'm starting to suspect that won't happen.

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](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
        }

~~~
wolf550e
That is the way it is done in C: avoid indentation if you can fail out. It is
very readable.

~~~
dyadic
I disagree, and saying "That is the way it is done in C" doesn't mean that
it's the right way.

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

~~~
tptacek
If you are religious about single-return style --- and I was an observant
practitioner of it until recently --- you simply aren't going to like Golang.

For that matter, if you _hate_ C programming --- not in the sense of "C is
dangerous and error prone" and more in the sense of "I hate the way I feel
when I write C code", you also aren't going to like Golang.

The former issue grinds on me a bit, though I'm coming to appreciate what it
does for the reliability of my code versus languages with exceptions. On the
other hand, I _love_ writing C code, and that probably makes up for it.

~~~
dyadic
I suspect you're right. I'm going to continue with Go for a little while
longer to give it a real chance, there are a few things I like about it such
as the dependency management and the lightning fast compilation so there's
still a chance that I will grow to like it.

~~~
tptacek
I really hate Golang error handling, but I have to grudgingly acknowledge that
it results in code that is more reliable than Ruby or Python (and _much_ more
reliable than C). That's a dividend paid by explicitness.

I would not say I've grown to like the error handling, but when I trudge
through it now, I do so realizing that there's probably an actual benefit to
my program of the annoyance.

The Go standard library is also really, really well designed.

------
sanswork
I've never known a language with so much discussion on why what you are doing
isn't idiomatic as Go.

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.

~~~
myg204
> I've never known a language with so much discussion on why what you are
> doing isn't idiomatic as Go.

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.

~~~
userbinator
_Python is another language where there is a lot of talk about idiomatic code
( 'Pythonic')._

I wonder what an appropriate adjective could be for idiomatic Go code. Gonic?
Gonian?

~~~
thrill
Gonic - causing a desired reaction - might work, though I suppose any correct
code would fit that definition. I sort of like gothic - always recognizable,
consistent, big.

------
jdkanani
As I go from normal Go style to idiomatic Go style, I find more error checks.
That is annoying when your code grows.

[http://talks.golang.org/2014/readability.slide#11](http://talks.golang.org/2014/readability.slide#11)

In this example, have to check error 3 times to write 4 lines of code.

~~~
libria
In Java, I'd have to write 3 catch blocks. It's possible to write a blanket
catch, toss it up to higher levels and make it someone else's problem. I
vaguely recall this being against Pike's vision of what "exceptional" means
and he wanted a language that forces developers to think of disk/network
failure as a very common case.

~~~
lclarkmichalek
Given that every single error check there is just passing up the error, is it
really that different from having exceptions that propagate along with RAII
style resource cleanup? The vast vast vast majority of Go code simply
propagates errors.

~~~
sagichmal

        > Given that every single error check there is just 
        > passing up the error, is it really that different from 
        > having exceptions that propagate along with RAII style       
        > resource cleanup?
    

Yes, it's fundamentally different. The _whole point_ is to make those error
blocks visible, so future maintainers are forced to deal with the reality that
those invocations are fallible. Maybe there's a way to make the error handling
less verbose, but hiding it altogether would subvert that explicit language
design goal.

~~~
lclarkmichalek
Except, you know, just mindlessly typing out "if err != nil { return }" does
not somehow force enlightenment upon the user. The error blocks are so uniform
in their banality that future maintainers treat them the same way that error
handling is treated in every other language.

~~~
invisible
The fundamental difference is that each separate error is accounted for rather
than 4 lines all being treated as error points so you never know which could
throw.

------
pjmlp
Sad that this is still the way to test for interface implementations.

[http://talks.golang.org/2014/readability.slide#17](http://talks.golang.org/2014/readability.slide#17)

~~~
webtopaz
It is a perfectly reasonable way to test for interfaces. A single struct may
satisfy a hundred interfaces which it doesn't even know about, this is
actually one of the best traits of go.

~~~
bsaul
I looked at this slide for a while and couldn't understand it. Could you
explain the detail a bit ? It seems like relying on dynamic type casting over
a nil variable, is that correct ?

But then what would the following "if" look like ?

~~~
webtopaz
This is how you can make sure that a struct implements an interface. The line
'var _ scan.Writer = (*ColumnWriter)(nil)' assigns a nil pointer of the struct
to a scan.Writer interface reference which would fail if ColumnWriter doesn't
implement the interface. And the casting always works.

~~~
bsaul
So it's a static typing check ? the code won't even compile if the
ColumnWriter struct doesn't implement the interface ?

~~~
webtopaz
Yes. It won't compile.

This check is not really needed as the code would fail when a function which
accepts scan.Writer would fail (compilation) if ColumnWriter is sent and if it
doesn't satisfy the interface. However, this is easier to debug.

~~~
NateDad
Yeah, this type of check is nice if you intend to implement an interface, but
don't actually use the type as that interface in your package. This will give
a compile time error if your type doesn't satisfy the interface. You could
write a test for it too, but this is a little simpler and harder to miss.

------
kremlin
I'm on Chrome on Mac and it's not entirely obvious how to navigate these
slides. Going to the link only shows me the first 3 slides by scrolling right.

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.

------
mratzloff
I found that I already do all of these as a result of reading through a lot of
the Go standard library when I was learning it. One of the best ways to really
learn a language is to read the standard library (the parts implemented in
that language, anyway). That way you get a sense of the idioms used, but also
understand the sometimes subtle trade-offs of common functions.

~~~
steveklabnik
This can be both good and bad. Two examples: The Rust standard library has/had
lots of awkward bits, from when certain language features didn't yet exist, or
before there was a convergence on how to accomplish something idiomatically.
The Ruby standard library has tons of Ruby code in it that's 20 years old,
that nobody has touched for various reasons. I certainly wouldn't write Ruby
in the same way.

~~~
mratzloff
Yeah. When I learned Ruby I read the Rails code base, which comes with its own
set of issues, but which was more modern and was a better representation of
the current state of Ruby.

------
lukasm
I don't get where is the bug in this code:

[http://talks.golang.org/2014/readability.slide#10](http://talks.golang.org/2014/readability.slide#10)

~~~
_blob
In the original code if out.Close() returns an error, run() will return nil.
The revised code sets `err` to the returned error from out.Close(), in case
the error from os.Create(*output) is nil.

Simply spoken, the original code will suppress the error from out.Close().

~~~
justinsb
What if the out.Write (which is presumably in "some code") has already set
err? Then we lose _that_ error, if out.Close returns error.

I think this is tricky in any language.

------
minhajuddin
Unrelated to the core presentation. I wrote
[http://readcode.in/](http://readcode.in/) to help with reading source code in
a simple single page format. It really fits go code repositories as they are
usually small. e.g.
[http://readcode.in/github.com/gorilla/mux](http://readcode.in/github.com/gorilla/mux)

------
zerr
Am I the only one who associates "Gopher" with Gopher (protocol)? Or is Golang
so much prevalent nowadays? :)

------
vegabook
Where's the gopher?! Idiomatic Golang presentations should include a non-
broken link to the gopher.

