
A year with Go - FraaJad
http://vagabond.github.io/rants/2015/06/05/a-year-with-go/
======
fixxer
Today, I got a request for a secure message passing service from our CTO. My
group, which is a small team of 2 *nix geeks in a company with ~20 mostly c#
developers, has become a bit of a skunkworks operation as we have been
responding to external constraints and forced to move quickly.

I was able to implement the service per the provided spec in 179 lines of Go
in about ~2 hours. Stress tests passed. The job is done. We march on.

Could I have written this service in C++? Absolutely, but it would have taken
me 20 hours to get to the same level of confidence. Maybe some could do it on
2 hours; I'm admittedly not a great C++ developer or frequent user.

Could I have written it in Python? Sure, but I would have had to scale and put
it behind a load balancer, adding complexity to get equivalent performance.

From what I've seen of Rust, I like it and plan to give it more time now that
it is stable. I haven't spent time with D. I played with Erlang. I don't care
for Haskell for anything remotely related to "work", but I don't dispute that
it has a place in computer science.

In my 2 years with Go, this is not my first positive experience. I have found
that Go works well for cranking out high fidelity, snappy services like this.
I think this is the result of the language's constraints enforcing simple
patterns. Unlike C++ and Python, there are not a huge number of ways to
accomplish tasks (at least not ways that feel natural).

Take it or leave it, but I like Go (for certain things).

~~~
threeseed
I don't understand what I am supposed to take away from this though. If you
were a strong C, C++, Java, Scala, Clojure etc developer you could equally
deliver a highly scalable solution in 2 hours. I haven't seen anything yet to
show why Go is fundamentally easier to deliver solutions except for single
binary development which isn't really an issue for server side development.

~~~
sagichmal

        > If you were a strong C, C++, Java, Scala, Clojure etc 
        > developer you could equally deliver a highly scalable 
        > solution in 2 hours.
    

I guess the point is, no, you couldn't. An equivalent solution would be less
robust/reliable or take (much) longer. Or both.

~~~
coldtea
With some of this languages it would have been much faster AND much more
reliable.

~~~
sagichmal

        > With some of this languages it would have been much 
        > faster AND much more reliable.
    

I don't think that statement is validated out by the body of evidence we have
about Go. But, this is all hypothetical, anyway.

------
4ad
> I also, apparently, don’t understand Go’s pointers (C pointers I understand
> fine). I’ve literally had cases where just dropping a * in front of
> something has made it magically work (but it compiled without one). Why the
> heck is Go making me care about pointers at all if it is a GC’d language?

Well, sorry, but if that's your level of understanding after _one year_ of Go,
I'm furious I wasted time to read your article up to that point.

~~~
baby
As I understand it, GO makes it so you can use both a pointer or the object
itself to access it methods.

And when you define an object method (or I don't know how it's called when you
do this:)

func (*string) uppercase(){

    
    
        // make uppercase
    

}

Then by saying you use a pointer means you will modify the value when you do
this: mystring.uppercase()

So it's not really pointers, it's more an idea of pointers.

~~~
xrstf
Things get ugly when your code grows. I had cases where I started with passing
pointers to structs around directly, but at some decided that having dedicated
interfaces would be better.

But as soon as you're talking interface, pointers don't work as expected
anymore, because Go (at least that's how I'm explaining it in my head) passes
_magic interface values_ to functions. So you can't just change `func foo(s
_MyStruct)` to `func foo(s_ MyInterface)`, but rather you probably want `func
foo(s MyInterface)`. Even though you are still explicitely passing a pointer
when calling foo() and whatever you're doing with s inside of foo() is working
on a pointer -- which your own function declaration doesn't even tell you
anymore.

This is one of the things that confuses the hell out of me when using Go.

~~~
twic
One of the most unhelpful things about Go's pointer syntax is that it collides
with HN's italics syntax. Hence, in your second paragraph, i see declarations
which differ only in the slope of the type. Really, does nobody think of this
when designing a language?

~~~
mbernstein
Are you seriously suggesting language designers should care about every sort
of markdown syntax that exists when determining how a language looks
syntactically?

Take a step back and think about your statement...

~~~
twic
For the avoidance of doubt, my comment was intended as a humorous way to point
out to the parent that they had got their code snippets mangled, and i am not
seriously advocating Markdown-compatibility as a language feature.

I'm curious, though, as to how you could _possibly_ think i was being serious.
Do you spend a lot of time interacting with people with insane ideas?

------
nemothekid
> _Adding proper mutexes to some of our code in production slowed things down
> so much it was actually better to just run the service under daemontools and
> let the service crash /restart._

Can the author explain this bit some more? If adding mutexes slows down your
code to the point where you would rather just deal with data corruption/races
it seems to me that there are issues with your code, not the language.

~~~
pcwalton
Yeah, that seems weird. A properly implemented mutex is one atomic instruction
in the uncontended path to lock and one more to unlock. And if you remove the
mutex, you're turning "the contended path" into "the path that blows up your
program". Atomic instructions can be painful on, for example, ARM (where they
turn into load linked/store conditional loop + memory barrier) but they
shouldn't be too bad on x86 servers.

(I have no idea how Go implements mutexes, though.)

~~~
seanmcdirmid
It is not unprecedented, e.g. see:

[http://en.wikipedia.org/wiki/Crash-
only_software](http://en.wikipedia.org/wiki/Crash-only_software)

Martin Rinard at MIT has done a lot of work in this area. It can be safe if
you can rollback to a good state to avoid data corruption.

Glitch, my current project, does not bother with reader locks for multi-core
execution; instead it can rollback and retry when a write-after-read is
detected effects are logged (dependencies are traced so write-after-reads can
be detected). It has performance benefits if you can amortize the book keeping
overhead, and we need to do it anyways to support live programming (see:
[http://research.microsoft.com/en-
us/people/smcdirm/managedti...](http://research.microsoft.com/en-
us/people/smcdirm/managedtime.aspx)).

~~~
nemothekid
I'm aware of crash only software (isn't this how Erlang/OTP does things?),
however this doesn't seem to be what the OP intended. Running your code
without caring about data races means your data can be corrupted and program
might not crash.

~~~
seanmcdirmid
It actually depends on what the code does, we don't get much context on what
the code is actually doing. It is completely possible that data corruption is
not a concern because nothing is being written, or there are checksums or
whatever...

------
coldtea
It's amazing how Go caught on.

It's not well designed -- lots of special cases reserved just for the
compiler, some bizarro decisions, etc.

It's not modern (with the possitive associates of modern, not fadish, and
modern being "the last 30 years of experience" which is still like a millenium
in IT years).

It's implementation is not great either. Not a very good compiler, not a very
good GC, not good tooling.

My theory is it caught on for 4 reasons:

1) It came from Google, and with some famous names to top. This got it initial
publicity in programming sites and media, and Google then coughed for
conferences, a spot on I/O etc -- so it caught lots of eyeballs, something
independent languages don't have a chance to do.

2) It produces static binaries and this was a real need for lots of use cases.

3) It's easy to get started with, and made converts from scripting languages
feel empowered, as if they were "real programmers" writing C, what with
"pointers" and static types.

4) It makes writing parallel code for some uses cases easy, which is a good
fit for some infrastructure/services apps.

(I don't think most teams outside of Google and some C++ or Scala shops have
had any beef with "long compile times" for that to have been a major factor.
Though it played to the hype of it being "just like a scripting language").

~~~
djhworld
> It's easy to get started with, and made converts from scripting languages
> feel empowered, as if they were "real programmers" writing C, what with
> "pointers" and static types.

What is wrong with this? Exposing people to pointers and static types might
give them confidence when writing or reading in "real programmers" code in C

I find the level of sneery nose turning in this thread quite abhorrent to be
honest.

~~~
nulltype
There seems to be an idea that some ways of telling your computer what to do
are too foppish and that if you are serious about it you use a language from
40 years ago. Of course that's probably what the assembly programmers said
about C and there aren't many of those left anymore.

------
mikeokner
I think the author gets closest to the mark in the Conclusion, but still falls
short. Go is very attractive as an "upgrade" from Ruby/Python or Java. It's a
good replacement for the interpreted languages when speed/performance matters
and it makes the async paradigm feel much more accessible. And compared to
Java, the fact that Go compiles to a native binary is a huge benefit. It's not
a replacement for C or a good "teaching" language, nor would anyone call it
"mature" at this point, but it does fill a niche and fills it pretty well.

[http://blog.disqus.com/post/51155103801/trying-out-this-
go-t...](http://blog.disqus.com/post/51155103801/trying-out-this-go-thing)

~~~
twic
> And compared to Java, the fact that Go compiles to a native binary is a huge
> benefit.

I'm baffled by this. I've been deploying Java applications for years, and this
has literally never been a problem. You build a WAR (or EAR, or uberjar, or
distzip, or whatever). You install a JRE on the machine. You deploy. You're
done. It's never been a problem for me, and it's not something that's talked
about as a problem in the Java community, which suggests it's not a problem
for other people.

When i see someone suggesting that Go has a significant advantage over Java in
terms of deployment, i assume that they don't actually have experience of
deploying Java apps, they're just regurgitating the standard Go talking
points.

~~~
falcolas
> You deploy. You're done.

Then you set your memory parameters. Then you tweak them, to make it more
performant. Then you increase them some more to make the GC work less. Then
you hook up to the JMX port so you can profile what's going wrong, and
identify some XML library as allocating megabytes of strings when it then
dumps. Then...

Yeah.

~~~
Alphasite_
Yeah. But you don't have to, you're literally complaint that the user has
options. It's not like Go doesn't have a GC either.

~~~
nosequel
Exactly, and Go's GC is years behind the JVM.

------
tptacek
I could be wrong, but I feel like when people talk about how great the Golang
tooling is, what they're really saying is "the compiles are instantaneous".
I'm sure he's right that the coverage tool isn't 100% perfect, or even 60%
perfect. OK. Fine. _The compiles are instantaneous_. Write a better one!

Golang is not an especially impressive programming language --- as a language.
But it seems to me like it is an undeniably impressive programming _tool_.

~~~
coldtea
> _I 'm sure he's right that the coverage tool isn't 100% perfect, or even 60%
> perfect. OK. Fine. The compiles are instantaneous._

Since when was compile time an interesting aspect to judge a programming
language? More in the "nice to have" category, especially if your program is
not 1 million lines and/or your language's compiler doesn't provide some
modularity in this regard.

~~~
tptacek
Have you ever worked on a large-scale C++ project?

~~~
pcwalton
Actually, the biggest problems with large-scale C++ projects for me have been
"long compile times _for fully optimized builds_ " and "long linking times",
neither of which Go 6g/8g solves.

Put another way, much of the problem is "modern compiler optimization takes a
long time". Go's solution was "remove the modern optimizer". That doesn't
actually solve my problem.

------
dvt
Funny how HN was on the Go bandwagon just a few years ago, and now an article
like this is almost unanimously upvoted (without much contrarian
discussion(!)).

I contributed to Go in the early phases and I really enjoyed using it and
learning it, but I found myself going to either Java if I wanted to write
something for production or Node if I wanted to write something as a
prototype. Unfortunately, I haven't used it almost at all for the past couple
of years :(

~~~
baudehlo
HN was the same about Node too. In a year we will see the same articles about
Rust.

~~~
sanderjd
See also: AngularJS, Rails, etc. A lot of this is just because things that a
technology makes convenient fade into the background after awhile because you
know longer feel the pain you felt before you had them, but you are actively
reminded of the things that annoy you about a technology multiple times a day.
For example, with Go, fast static compilation and "just works" deployment
fade, while the copy-paste-tweak pattern for generic behavior continues to
bite. For Angular, you start to forget how much easier it made defining
modular view components and having up-to-date data everywhere, while actively
finding complexity and performance frustrating.

I'm sure you're right about Rust, and that people will be down on lifetime
annotation burden, painful compilation times, painful data structure nesting,
the complexity of unsafe code, and other things, while forgetting all the
times things are actually easier, more performant, and safer due to all that
language support.

I see it as a natural damping curve: at first things seem peachier than they
really are, then they seem much more frustrating than they need to be, then
you come to terms with their unique trade-off of strengths and weaknesses.
What I _would_ like to know – if anyone here has discovered such a thing – is
a way to skip to the last step more quickly.

~~~
ascendantlogic
As I get older and I gain more perspective, I can't stress enough how true
this is. Listening to younger programmers bemoan Ruby and Rails is humorous to
me because they don't remember the world of Java web dev before Rails. Miles
of XML configs everywhere, factories, impls, proxies, beans. So. Much.
Boilerplate.

It's easy to bitch about things the way they are now, but understand there are
people and technologies who were around before you arrived on the scene and in
general, things are consistently getting "better", for all subjective
interpretations of "better".

~~~
Dewie3
Now I'm confused. I've heard that we should learn and appreciate that nothing
is new under the sun and most interesting concepts and technologies have
already been invented in the past and not newly by newer technologies. Now
you're saying that newer technology consistently _improve_ things? I'm getting
confused as to how the older hive mind is telling me to feel.

~~~
jballanc
Concept and implementation are not the same thing. The _concept_ of LISP
hasn't changed in 50+ years, but the implementations have been constantly
improving the whole time.

------
smegel
> if I wanted a language built around concurrency I’d use Erlang or Haskell.

And if you wanted a concurrent language that wasn't a functional language what
would you use?

~~~
eloff
Or just a practical concurrent language with strong libraries that lets you be
productive quickly. I'm aware of many of the theoretical benefits of Erlang
and Haskell over Go. But Go is still a much better choice for getting things
done.

~~~
codygman
As someone who used Go in the past for work and now uses Haskell, I can say
that the advantages of Haskell over Go are more than "just theoretical".

In my day job I use Haskell to "just get shit done". However when it comes
time to refactor I can do it much faster and safer in Haskell.

The ease of refactoring creates an incentive to improve code.

~~~
eloff
My experience is the exact opposite. Maybe we work on very different kinds of
problems, or maybe it's just because we're different people.

~~~
codygman
> Maybe we work on very different kinds of problems, or maybe it's just
> because we're different people.

In the interest in figuring out which, what problems do you work with and what
are your principles/beliefs/guiding principles in software? :P

------
Arzh
The point isn't about learning something new. It's about trying to apply those
things into a language they think is easier to work with.

~~~
eloff
I'd argue the point is the opposite of learning new things. As the Go team
themselves say, Go is an engineering project. It's about sticking to well
understood, well defined ideas that allow large teams of typical skill to
develop and maintain good software. Go is boring compared to some other
languages that push the envelope and try new things. But that can be a good
thing if you start thinking like the business owner instead of a code monkey.

~~~
0xdeadbeefbabe
Most people won't see it this way, but not pushing the envelope _is_ a new
thing.

------
ffn
If backend programming was epic fiction, then right now, the world is divided
into the following countries: The Kingdom of Java, The United Languages of
.Net, and the Confederacy of the Scripting Tongue (where racial tensions are
crackle under the temporary truce between Ruby, Python, Javascript, Lua,
etc.). For the past decade, these three kingdoms constantly struggled against
each other for the most precious resource of all: developer mind-share.

But what they didn't know and couldn't prevent, was that their world would
soon become (neigh, has already become) the battle ground of 3 ultra-advanced
warring alien species: Go, Rust, and Elixir. Backed by unimaginably powerful
forces (except Elixir, which is just open-source by Poland's own Jose Valim),
the upstart alien languages threaten to herald in a terrifying future for the
current 3 powerhouses.

OP's article, and the fact that lots of people are agreeing, is a sign that
one of the invading aliens is weakening.

~~~
ericdschmidt
I want to watch this movie.

What about Pony?

------
tmsh
What's confusing about Go, in comparing it to other languages, is that it's a
minimum orthogonal refactor of a language. It was born out smart engineers
observing the web and other languages for decades and thinking that they
needed something low level but high level enough. It's built staring precisely
at the past two decades.

C, C++, Java, Python, and an appreciation of formal specs over frameworks form
Go.

Most languages to perform professionally in you have to know what not to do
(not use C++ templates too much, not give into verbosity in hierarchies in
Java, not use the GIL, etc.). In Go, because it is a relatively clean
refactor, you don't have to worry about this.

But you do have to invent your own smaller libraries for what you want to do
sometimes. Because it's a younger language. This is good though if you like
programming and stacking lego pieces on you way to stacking paper.

------
fishnchips
> Good languages help evolve your approach to programming

Go certainly taught me quite a bit about closures and programming to an
interface.

------
samora
I think a lot of us miss the Go point.

There is nothing special about Go. It's simple and just works.

Every time I used Go for a project it just worked. No fuss. With very little
effort. And that's the point.

~~~
gambiter
But that doesn't answer any of the (very valid) points raised in the article?

Go is interesting as a replacement for a scripting language, perhaps. But it
seems very lacking in many other areas. All of the points in the article, plus
what libraries are available.

I think some of it could be explained by it being a young language, but if
that's the case, why is it getting the adoption it has so far? Just because it
came from Google?

~~~
rakoo
Because it has allowed so many of us to significantly raise the ratio "Amount
of time I care about my project"/"Amount of time I care about something other
than my project (typically, the language itself)".

Go is the poster child for Worse is Better. It's ugly, inconsistent, feels
naughty at times (all those copy-pastes ! It's so un-DRY !) but it gets shit
done.

------
larryweya
I've had a keen interest in go but haven't used it for anything serious. My
impression of it is that its a great replacement for languages like Python and
is great at getting things running fast but I have to agree that it doesn't
feel like the kind language I wouldn't want to write a large code base in. My
huge interest in it is around the single binary deployment and its concurrency
model. The language itself I find a bit quirky in some places (some data
structures are passed by ref while other by value) and I like my languages
concise and elegant.

This post got me to have a second look at Elixir and I spent the whole day
going though its documentation and prototyping an idea I wanted to implement
in go, specifically because of go's concurrency model. And frankly ELixir is
exactly the right fit for me, not only for this case but generally as a
language with the kind of elegance and expressiveness I'm drawn to.

------
namelezz
I always find it's difficult to navigate Go repositories on GitHub. Because
there can be several source files under a package it's difficult to look for
an implementation of a function or method. For Java, I can easily guess where
the methods are by looking at import statements.

~~~
kjksf
I friend of mine wrote a tool to fix that. See
[http://gotools.org/github.com/kjk/fofou](http://gotools.org/github.com/kjk/fofou)
for example (just prepend [http://gotools.org/](http://gotools.org/) to any Go
import path).

Then you can use Ctrl-f (Cmd-F on mac) search built-in browser to look for
things.

It doesn't work for large repositories but most of them aren't.

------
nickysielicki
> "I just don’t understand the point of Go. If I wanted a systems language,
> I’d use C/D/Rust, if I wanted a language built around concurrency I’d use
> Erlang or Haskell."

Agreed. C and Rust are systems langauges, Go is not particlarly great in that
category. That is okay.

I will say, I hope you have fun getting an average CS graduate to properly
write and maintain a Haskell or Erlang program with concurrency. Go is stupid
easy to pick up for anyone who has worked with C/C++/C#/Java/Python/Ruby,
which, by no exaggeration, probably encompasses every programmer alive.

Meanwhile, Haskell and Erlang look like gibberish to most programmers. And
I'll admit, that's a lacking argument. Functional languages cannot be said to
be bad just because most people don't understand the functional paradigm.

But the fact remains, an average programmer can sit down today with no
knowledge of Go, and by the end of the day create a concurrent program using
Go. And given the lack of flair in go, it's _the_ langauge that lends itself
to being maintainable. You won't see anything like in python or perl where
you're almost expected to abuse the langauge internals (see this awesome
example in python [0]). That's completely by design. [1][2] (scroll up to see
the quote by Rob Pike)

If you have a team of a dozen guys working on a project with thousands of
lines, your priority is not just performance (Go is quick enough [3]). It's
probably not elegance either.

It's software that documents itself.

I used to work as a systems administrator for my schools engineering
department. We would deal with fixing perl scripts dating back to the 90's. As
students came and went, the result was hack jobs on top of hack jobs by
students who are now in their 30's. I hated it. I would commonly have to
rewrite scripts because over the years the basic flow of the program became
completely asinine.

That's exactly where go does well. Go is a langauge for people who don't want
to have to deal with abuses of the language that their coworkers put in place.
Go is a language that understands that for programmers, maintaining code means
fixing bugs and fixing bugs tends to boil down to hacky solutions. Go ensures
that those quick fixes aren't hacks.

> "The only place I can see Go shining is for stuff like portable command line
> utilities where you want to ship a static binary that Just Works(tm). For
> interactive tasks I think it would be fine, I just don’t think it is
> particularly well suited to long-running servery things."

I really don't understand why he feels that way. I don't see the distinction.

> "It also probably looks attractive to Ruby/Python/Java developers, which is
> where I think a lot of Go programmers come from. Speaking of Java, I
> wouldn’t be surprised to see Go end up as the ‘new Java’ given the easier
> deploy story and the similar sort of vibe I get from the language. If you’re
> just looking for a ‘better’ Ruby/Python/Java, Go might be for you, but I
> would encourage you to look further afield."

This reminds me of The Story of Mel [4].

If you're someone who enjoys programming and are writing the code for fun, I
agree. Find the most unique language and do it in the most elegant way.
Programming is almost an art, and if you're trying to be artistic, unique
langauges are great for it.

But not all software is artistic.

> "Good languages help evolve your approach to programming; LISP shows you the
> idea of code as data, C teaches you about working with the machine at a
> lower level, Ruby teaches you about message passing & lambdas, Erlang
> teaches you about concurrency and fault tolerance, Haskell teaches you about
> real type systems and purity, Rust presumably teaches you about sharing
> memory in a concurrent environment. I just don’t think I got much from
> learning Go."

I don't think that all langauges need to be learning experiences. Sometimes
you just need to get shit done.

[0]: [https://benkurtovic.com/2014/06/01/obfuscating-hello-
world.h...](https://benkurtovic.com/2014/06/01/obfuscating-hello-world.html)

[1]:
[https://talks.golang.org/2012/splash.article](https://talks.golang.org/2012/splash.article)

[2]: [http://nomad.so/2015/03/why-gos-design-is-a-disservice-to-
in...](http://nomad.so/2015/03/why-gos-design-is-a-disservice-to-intelligent-
programmers/#fn-601-1)

[3]:
[https://benchmarksgame.alioth.debian.org/u64q/go.html](https://benchmarksgame.alioth.debian.org/u64q/go.html)

[4]: [http://www.catb.org/jargon/html/story-of-
mel.html](http://www.catb.org/jargon/html/story-of-mel.html)

~~~
felixgallo
> But the fact remains, an average programmer can sit down today with no
> knowledge of Go, and by the end of the day create a concurrent program using
> Go.

If there's any benchmark more pointless than the alioth benchmarks game, it's
the 'what can a novice programmer do with the language in the course of 8
hours' benchmark.

There are zero businesses that operate by giving novice programmers 8-hour
tasks in unfamiliar languages.

~~~
ascendantlogic
The first company I was at prided itself on the "sink or swim" method of
hiring. You'd be surprised how many developers out there judge new hires by
how quickly they show they can start shipping code.

~~~
crimsonalucard
It's the wrong approach, but it does happen.

------
webkike
When I use Rust I am constantly annoyed by how limiting traits are in
comparison to interfaces. I much prefer interfaces, which are a single type,
as opposed to traits, which are sets of types.

~~~
Manishearth
I don't see how traits are limited.

Traits are types, though you need to put them behind a pointer (Box<Trait> or
&Trait) if you want to use them as types; and this is dynamic dispatch.

You can use them in static dispatch (generics) too, and in general you should
try to do that whenever possible. Plus there are loads of things you can do
with them that Go can't (static trait methods, associated items, generics,
etc)

The only feature that Go interfaces have that Rust traits don't is auto-
implementation, and that's a misfeature IMO. It works okay for Go, but in Rust
it makes more sense to explicitly say that you are implementing a trait.

------
tapirl
> Why the heck is Go making me care about pointers at all if it is a GC’d
> language?

Apparently, the author doesn't understand how pointers work in Golang. He
should read this article: [http://openmymind.net/Things-I-Wish-Someone-Had-
Told-Me-Abou...](http://openmymind.net/Things-I-Wish-Someone-Had-Told-Me-
About-Go/) . In short, golang pointer is neither c pointer nor java reference.

------
rkapsoro
Go is great and all, but I'm really only using it until Rust is ready.

~~~
artursapek
Rust 1.0 came out recently. What are you waiting for?

~~~
fsaintjacques
Complete, stable and mature standard lib.

------
jtwebman
Sweet, I'll stick to learning Elixir with some (Erlang)!

