

Examples of beautiful Go? - riyadparvez
http://programmers.stackexchange.com/q/82179/19141

======
jgrahamc
To a certain extent the question is not correct. Go was not designed to be
beautiful, it was design to be readable. So the code can look quite pedestrian
(e.g. for { } loops where other languages might have other constructs).

I believe this to be a win because learning and writing the language are fast.
There are some nice 'a ha' moments (such as when you understand interfaces),
but mostly the code is (in a good way) boring.

It's also a small language. I think it was designed for people who want to get
things done, not for people who want to find the cleverest (i.e. least-number-
of-characters) way of doing it.

The way concurrency is built into the language (based on sequential
programming with channel based communication) further reduces the potential
complexity. You just write sequential code and let the Go runtime handle the
rest.

~~~
randomdata
Beauty is inherently linked to readability, at least in my opinion.

If you look at typesetting, a lot of care is taken to tweak letter spacings
and getting the font just right. This makes the work easier to read than a
giant wall of text, and visual beauty comes as a natural side effect of that
optimization.

Code really isn't any different. While there is certainly some variance by the
beholder, code that is generally easy to read is going to naturally look
beautiful. Additionally, and perhaps more importantly, if the code is
beautiful, it will attract you to maintain it.

I am still a Go newbie, but my initial impression is that certain constructs
make it more difficult to write beautifully than it should, which only serves
to detract from the readability (not talking clever one-liners here – which
shouldn't even come up in beauty discussions). However, given that I am new to
the language, I may just not be yet able to express things as well as I could.

~~~
jbooth
Coding is completely different from typesetting, otherwise we wouldn't all be
using monospace fonts.

Beauty's more subjective than readability, but most of the time a beautiful,
elegant, recursive structure takes more time to figure out than your ho-hum
for loop, in my experience at least.

~~~
4ad
Not everyone. I certainly don't :-). A significant minority of Go users come
from or like Plan 9, and they use acme or sam, Rob Pike's editors, which by
default display text in a variable width typeface.

~~~
jbooth
Huh, so I guess you guys just use tabs rather than spaces to get things to
align properly?

~~~
zemo
we use whatever `go fmt` outputs (which, yes, happens to be tabs).

------
voidlogic
"Because of that, I'm having trouble persuading myself that Go is much more
expressive than competitors" Beauty is in the eye of the beholder. While one
programmer might say beautiful code is expressiveness (ex. performing a one
liner quick sort), that is not what most Go developers I know see as beauty.
Beautiful Go in my opinion is code that (in increasing importance):

    
    
      1. runs fast
      2. uses little memory
      3. is easily made (or is) concurrent / parallel
      4. is transparent (the intuitive run time complexity of operations is apparent, no hidden O(n..) operations, etc)
      5. is easy to maintain
    

If this code happens to be more verbose than say Java, so be it, it is still
beautiful. On an anecdotal note, most large C++, Java and node.js projects I
have ported to Go have ended up being fewer LOC in Go.

~~~
melling
How does a Go solution compare to a Perl, Python, or Ruby solution? The latter
languages offer quick solutions to problems but they don't often scale to
large projects built by large teams.

~~~
jweir
Binary builds are one advantage. Compile your go application and deploy it. No
need to also install Ruby, gems etc.

You can cross compile as well. IE compile for Linux from OS X.

[http://dave.cheney.net/2012/09/08/an-introduction-to-
cross-c...](http://dave.cheney.net/2012/09/08/an-introduction-to-cross-
compilation-with-go)

~~~
danieldk
Imagine that Go were used to write most components on a system. One security
vulnerability in one package and you don't replace just one library, you'll
have to reroll every binary (or package if you are maintaining a Linux
distribution).

Also, since there is no version management in Go packaging, you better hope
that every program uses the API of the latest or fixed version.

~~~
burntsushi
> Imagine that Go were used to write most components on a system. One security
> vulnerability in one package and you don't replace just one library, you'll
> have to reroll every binary (or package if you are maintaining a Linux
> distribution).

Imagine that a shared library were upgraded, and it contained a new
vulnerability. This vulnerability now automatically exposes any program that
uses said said library.

Trade offs :-)

(Compiling Go is fast. Re-rolling a binary isn't a Big Deal.)

> Also, since there is no version management in Go packaging, you better hope
> that every program uses the API of the latest or fixed version.

Simplicity has a price. But there's no reason why an external tool cannot be
made to handle versioning.

~~~
danieldk
_Imagine that a shared library were upgraded, and it contained a new
vulnerability. This vulnerability now automatically exposes any program that
uses said said library._

Production systems normally only replace shared libraries to fix
vulnerabilities. So, that's a non-argument.

On non-production systems, it's far easier to replace one vulnerable library,
than tens of vulnerable Go programs. That is, if you know which Go program was
using what version of that package again.

~~~
cmccabe
Do you feel comfortable ripping out a shared library used by many different
binaries on a production system and replacing it with a new one? I would be
pretty scared to do that.

I would rather replace all the binaries separately. If one of the new binaries
didn't work, I could go back to the old version.

I do agree that the shared library approach uses less network bandwidth, but
is that really a big problem these days? Unless you're sysadminning over
dialup, chances are you don't really care. The size of binaries has plateaued
at a meg or two even as networks have continued to improve.

~~~
danieldk
Sure, I know when the ABI changes and when not. For security fixes it's pretty
safe to do. In fact, Debian Stable et al. do it all the time.

------
munificent
Caveat: lots of subjectivity here.

My impression is that Go and Lisp are similar here. Neither is particularly
pleasant to read in the small. Lisp because of all of the parens and the
sometimes "backwards" dataflow of nested functions. Go because of the
"imperativeness", the frequent manual returns for errors, the mandatory {} for
blocks.

In both cases, that was a deliberate choice in order to get _simple_ syntax.
The beauty they are focused on is larger-scale beautiful _semantics_. Lisp
with macros, first-class functions, etc. Go with interfaces, goroutines, and
channels.

Where some languages treat the syntax as a first-class feature, I think Go and
Lisp treat it more as a means to an end. That being said, in both cases,
practitioners of those languages do specifically like their syntaxes. It's
just not a major focus of the language designers' time.

~~~
bitops
_> Lisp because of all of the parens and the sometimes "backwards" dataflow of
nested functions._

I've come to believe that the second part of this statement really is the
primary reason why Lisp drives some people absolutely nuts. The parens are
really just a distraction and "easy" justification for not liking the
language.

It makes sense, though. When you have to read both "outside in" and "bottom
up", a lot of your acquired reading abilities (left to right, top to bottom)
are in tension with the code you're trying to understand.

At least in Clojure, the ->> family of operators ("threading" macros) are
doing a good job helping to alleviate this. Maybe they're available in other
Lisps, I don't know.

 _EDIT:_ found a reference to these macros in Emacs Lisp:
<http://emacswiki.org/emacs/ThreadMacroFromClojure>

~~~
munificent
> I've come to believe that the second part of this statement really is the
> primary reason why Lisp drives some people absolutely nuts.

Agreed. This is a major reason why Lisps read wrong to me and is one of my
favorite things about conventional subject.verb(object) syntax in OOP
languages.

My own language[1] has Lisp-like semantics where methods are lexically-scoped
and not attached to classes but retains something close to OOP syntax because
I think that's such a readability win. For me, this is the best of both
worlds.

[1] <http://magpie-lang.org/multimethods.html>

------
chimeracoder
Go fmt is my single favorite feature about the language.

Coming from a background in Lisp, I don't find much in Go that seems very
'elegant' or 'beautiful'. What I find is that everything - including the Go
source code itself - is perfectly standardized (and therefore immediately
readable).

I don't have to worry about different coding styles, about semicolons vs. no
semicolons[0], about having more than one way to express the same code. I can
skim the code easily because the structure is so uniform across all standard
and community libraries.

That's a different kind of beauty from chaining macros and cons cells, but
it's beautiful nonetheless.

[0]<https://github.com/twitter/bootstrap/issues/3057>

~~~
jweir
Not only does gofmt make the code consistent for people, it makes it machine
consistent. Once the code is "fmted" parsing, replacing, etc is simple.

Which, btw, gofmt does does pattern replacement.

<http://golang.org/cmd/gofmt/>

~~~
shurcooL
The pattern replacing is awesome. It can do a lot of refactoring.

[http://talks.godoc.org/github.com/sunfmin/talks/2013/gofmt.s...](http://talks.godoc.org/github.com/sunfmin/talks/2013/gofmt.slide#1)

~~~
pjmlp
If this is refactoring, then you never used a proper IDE with refactoring
support.

Slide 5 is the proof this is no better than search and replace.

~~~
NateDad
Honestly, that's not a very good representation of what gofmt can do.

This is a much better example: <http://research.swtch.com/gofmt>

gofmt -w -r 'x[i:len(x)] -> x[i:]' *.go

Note that this is not a regular expression... it's looking for go expressions
that match that pattern.

So, for example, this will catch this:

a := charts[start:len(charts)]

and convert it to this:

a := charts[start:]

~~~
danieldk
True, it's much more than simple search and replace, since it produces an AST,
which provides more powerful refactoring.

It's also not very spectacular, since it's what Java IDEs have done for ages,
plus incremental compiling :). (Or code analysis tools such as Sonatype.) Go
is just playing catch-up here.

The one thing they did very well is dictating the code style with gofmt. You
may not like it, but at least there is once standard. Though, one wonders how
many developers and businesses use whatever layout Eclipse or Netbeans use out
of the box ;).

------
rwj
Conciseness was not a goal. Simplicity and regularity were. IN this case,
beauty is in the eye of the beholder.

~~~
eric970
Agreed.

------
mortdeus
Omg ruby is so much better. K thnx bye.

~~~
eric970
LOL. I know this is a joke, but I'm actually a ruby dev myself diving into Go.
I find it to complement Ruby extremely well. Both have their strengths and
weaknesses.

------
mortdeus
Sorry didnt think this post had enough troll in it to qualify as an authentic
go discussion.

