
A little Golang way - vonsnowman
https://www.aerofs.com/blog/a-little-golang-way/
======
travjones
There have been several blog posts and conference presentations with a similar
theme -- "Go is efficient, especially compared to X."

I know it seems like hype, but I encourage others to try Golang out, maybe
even slap a web app together with it. What you'll find is that your Go app
will be extremely efficient and performant. It's kind of unfair to compare Go
to many of the other languages of the web because it is compiled, which is a
huge reason why it is so performant. So rather than compare Go to other
languages, I encourage you all to give it a try. If you already program,
working on a small Go side project will get you up to speed quickly and you'll
learn about some of the awesome packages individuals from the Go community
have put together for us.

Disclaimer: I do not work for Google. I write Go code and enjoy it. I think
others will too.

~~~
eropple
_> What you'll find is that your Go app will be extremely efficient and
performant._

This is true, for sure. But my experience--and I've written plenty of Go,
though I find it unpleasant to write and think about for all the usual reasons
that Go partisans roll their eyes and so would rather deal with it as
artifacts rather than actually writing it--has led to watching lots of
developers make mudball codebases in the process (while blogging very heavily
about how great it is three weeks in, and less a year-plus in). A pursuit of
faux-simplicity has led to what I see as reinventing a lot of Java-1.4-era
(because the language itself is essentially that) design patterns--and we
should be reminded that design patterns exist to address defects in tooling--
that more expressive languages have managed to avoid; the general desire for
smaller applications helps to some extent, but software has this tendency to
grow that I don't think Go gives you the tools to effectively manage and
maintain. Reasonable minds can differ, of course.

Past that, while I think it's an alright choice for company-internal
deployable products--web servers, worker nodes, etc.--I have straight-up
problems with it being the new devops tool of choice. Statically linking your
SSL library makes you an asshole when it inevitably fails and now an
application has to be regression-tested so that new features and new bugs
don't hose you just because that's the only way to upgrade Heartbleed 2.0. (Go
also discourages program extensibility through components and rather as
recompilation; the stuff Packer and Terraform do to provide "plugins" that the
same company's Vagrant just did with a `require` is gross and, to my mind,
completely foolish.)

So I wouldn't say it's _hype_ , but I would say it's not all _true_ , either.

~~~
grey-area
_reinventing a lot of Java-1.4-era (because the language itself is essentially
that) design patterns_

Really? Java 1.4 had an extensive and consistent standard library, implicit
interfaces, composition instead of inheritance, static builds, and built-in
concurrency?

Go is not early Java, it's more like C 2.0, and I don't really see anything
faux about the simplicity, it really is pretty simple, perhaps too simple for
some tastes, but it's not pretending to be simple, nor is it simplistic. Which
specific design patterns did you have in mind?

~~~
chadaustin
> extensive and consistent standard library

yes

> implicit interfaces

no

> composition over inheritance

yes

> static builds

no

> built-in concurrency

sure, with an 1:1 thread model as opposed to an M:N thread model.

M:N is not always a clear win over 1:1:

[https://mail.mozilla.org/pipermail/rust-
dev/2013-November/00...](https://mail.mozilla.org/pipermail/rust-
dev/2013-November/006550.html)

[http://xiao-feng.blogspot.com/2008/08/thread-mapping-11-vs-m...](http://xiao-
feng.blogspot.com/2008/08/thread-mapping-11-vs-mn.html)

Also, to be very clear, Java's threads ("green threads") were _originally_ M:N
but they switched back to 1:1.

~~~
cgag
I don't know if the programming model of threads and channels that's used by
haskell and golang strictly depends on the existence of M:N threading, but it
sure is nicer to use than the model in java/rust.

~~~
threeseed
Go's channels/threading model already exists in Java:

[https://github.com/puniverse/quasar](https://github.com/puniverse/quasar)

~~~
skj
It wasn't immediately obvious from scanning that link. Does it provide channel
select? Because that's the hard part. Threadsafe queues are easy, select on
them is hard.

~~~
pron
Of course it does.

Java:
[http://docs.paralleluniverse.co/quasar/javadoc/co/parallelun...](http://docs.paralleluniverse.co/quasar/javadoc/co/paralleluniverse/strands/channels/Selector.html)

Clojure:
[http://docs.paralleluniverse.co/pulsar/api/co.paralleluniver...](http://docs.paralleluniverse.co/pulsar/api/co.paralleluniverse.pulsar.core.html#var-
select)

We'll have a nice slect API for Kotlin, too, very soon.

------
sz4kerto
"Code size was reduced by almost half, from 175 lines down to 96."

Hm, I how can we take a 175 LOC project as something relevant in any way?

~~~
mkozlows
The relevance is that even a 175 LOC project in Java takes up enormous memory
and disk footprint -- that the JVM is this super-heavyweight thing that's
really just inherently inappropriate for a lot of applications.

~~~
xienze
> The relevance is that even a 175 LOC project in Java takes up enormous
> memory and disk footprint

_This particular_ 175 LOC Java project takes up an enormous amount of memory.
For all you know it was just coded poorly and the Go one is a bit more
reasonable.

> the JVM is this super-heavyweight thing that's really just inherently
> inappropriate for a lot of applications.

The JVM introduces overhead but not so much that you can make these sorts of
extrapolations.

~~~
vonsnowman
The footprint of this particular service could have been optimized in Java
but:

    
    
      1. the JVM itself imposes a high floor (hotspot, many shared libs loaded, ...)
    
      2. the Java language is full of overhead at every level (boxed types are a pet peeve of mine)
    
      3. the Java ecosystem has a tendency to regard memory as an inexhaustible resource, which lead a lot of waste in many 3rd party libraries
    

The core point is that optimizing this particular Java program (and the others
that followed) would have been more time-consuming than a Golang rewrite and
would have probably increased the complexity whereas a Golang rewrite reduced
it.

Optimization was the original goal, increased maintainability was a pleasant
result.

~~~
vardump
Point 2... yeah, that's one of my major problems with Java. Unnecessary boxing
and the unreasonable amount of complexity if you work around it. In any type
of Object collections, it consumes memory, stresses garbage collector
unnecessarily and causes a lot of CPU cache misses.

Value types would help so much with this issue. I know they're coming one day.
I hope Java/JVM can replicate memory efficiency and cache coherence of C++
std::vector for small objects.

------
skarap
I guess nobody will be saying that Java is lightweight, but the actual results
of porting from Java to Go will vary wildly from usecase to usecase.

Both examples mentioned in the article (the 175LoC program and the CA) sound
like very simple programs. E.g. I once wrote a C program which watched some
directories with inotify and compressed new files using zlib. The memory
footprint was 350KB. Obviously an empty JVM alone would use 100x more RAM.
This static ~30MB overhead might be important in some cases and not relevant
at all in others. The incremental (per-object) overhead is probably more
relevant to almost all real-world usecases which are a bit more complex then
the ones mentioned above.

Also - care should be taken not to compare apples (no TM) to oranges: e.g. if
you use a huge ORM in Java (which among other things also caches results of
each query) and then do a simple SQL query in the new implementation, would be
strange to expect those two to perform similar. This happens quite often with
rewrites - they almost always aim for simplicity, do short cuts, get rid of
"unused stuff". Basically a rewrite from Java to Java will also usually
improve performance.

Must-read about rewrites:
[http://www.joelonsoftware.com/articles/fog0000000069.html](http://www.joelonsoftware.com/articles/fog0000000069.html)
. Though, I guess, everybody has already read it.

------
carloscarnero
At my organization we have several Java-based services (some of them can even
qualify as a form of microservices, if you squint your eyes). We have found
that when you have very good developers and you write almost to the letter of
the spec, Java can easily provide a stable base (which is probably true of any
language/runtime/library).

However, we've been eager to try Go in several places. Believe it or not, what
has held us back is the lack of a solid LDAP library. We could/should scratch
our own itch and be done with it, we lack the time... still so many things to
do! In the mean time, for us, Java support for LDAP is nothing short of
stellar; and has been for years.

------
jsnk
More and more I hear about Go, I feel more convinced that it would be worth
giving it a shot.

Can you share what the microservices are doing? What are they for?

~~~
vonsnowman
At this point we have 6 microservices written in go in the appliance:

    
    
      - team-server probe: already mentioned in the blog post.
        Determines if any installed Team Server is down.
    
      - ca: as mentioned in the blog post, as simple Certificate Authority
    
      - charlie: a checkin service. Desktop clients periodically post to it
        to signify they are up. This data is used in each user's device list
        to show if the device is up and which ip it was last seen from.
    
      - auditor: takes audit event in an HTTP endpoint and forwards
        them to a raw TCP connection as expected by splunk and co
    
      - valkyrie: a relay server used for data transfers when desktop
        clients cannot establish direct TCP connection (more about that
        in a future blog post)
    
      - lipwig: a messaging/pubsub server used for peer discovery
        and notifications (more about that in a future blog post)

------
bliti
I've been writing Go for some time. Just finished writing a small CDN for the
company I currently work for. It's It's a fast language that performs well in
systems programming (what it was made for). But boy is it ugly. Not verbose
like Java, but ugly to write and read. It does force a good coding convention
because otherwise you end up with a pile of ugly code. People seem to be bent
on writing it like 80s C. Full of single character variable names and odd
function naming. Dunno if it's just my experience. I do like the fact that it
resembles python in how it feels. Overall I'd say it's a nice language that is
not for everybody. I am playing with Elixir these days. Go is good enougb, but
I'm not happy with it being that.

------
anoother
Something troubles me about this article. I hope I'm misunderstanding it.

It's stems from the following quotes; knowing this information, why do AeroFS
still think Docker is a good fit for their use-case?

> However, after our move to Docker, we noticed a sharp increase of the
> appliance's memory footprint.

> ...

> We identified several major factors behind these symptoms:

> 1\. an increase in the number of running JVMs, as each tomcat servlet was
> placed into a separate container

> 2\. reduced opportunity for the many JVMs to share read-only memory: the JVM
> itself, all the shared libraries it depends on, and of course the many JARs
> used by multiple services

> 3\. memory isolation could in some cases confuse some sizing heuristics,
> which lead to larger caches being allocated by some services

~~~
ambrice
Presumably Docker offers some benefit. It's weird that you and several others
have jumped to the conclusion that it's obvious they should get rid of Docker.
I would say: knowing this information, why do you still think java is a good
fit for their use-case?

~~~
anoother
Because:

a) Their service was already written in it b) Their service was already
performing adequately before they brought docker into play

But those aren't answers to your question. Java may have been a __terrible
__fit for them, but their decision to move away from it was not motivated by
that -- it was motivated by their already-written, already-performing Java
code no longer performing as well, __because of Docker __.

The only question is, does Docker bring them __enough __benefits to justify
reimplementing large amounts code, in a new and unfamiliar language? Maybe it
does, but somehow I doubt it.

------
djhworld
I find this article confusing, in the first part the writer talks about Tomcat
and servlets, in the second part he talks about reducing the LOC from 175
lines to 96 by using Go.

To me it seems the Java solution was wildly over engineered and probably could
have been refactored to not even need Tomcat.

------
themartorana
I am not sure I understand where the issue is Java pure and simple, and where
the issue is that Java services were impaired by being wrapped by Docker?

"Everything was fine until we switched to Docker" makes me think the trouble
may not be all Java. Anyone have educated thoughts on this?

------
colordrops
Wow that pun in the title is painful.

~~~
sumobob
Theres a pun in the title?

~~~
axyjo
It's from a saying... a little goes a long way.

~~~
BinaryIdiot
Thank you; I didn't understand it either.

------
jaytaylor
Can anyone shed some light on how/why running the same Java apps in a docker
container significantly increased the memory footprint?

Is JVM overhead shared when multiple Java apps are being run on the same
machine?

~~~
haldean
A lot of it is, yes. The JVM loads a large number of largeish class files when
it starts; these contain implementations of the standard library and whatever
else is on your classpath that you've imported. These have the nice property
that they're read-only, though, so multiple JVM processes can safely share
them. When you move to sandboxing each JVM off by itself, you lose the ability
for them to share memory (which is, in a sense, a _feature_ of sandboxing), so
now each of them has to take the 50-100MB hit of those formerly-shared memory
regions.

(Note that the huge size of the classes is also the big reason why JVM startup
time is so crap; another reason that multitenant JVM systems are great is that
every process after the first starts much faster)

------
lpsz
Anecdotes like this makes me wonder how much funding money and electricity
could be saved if people migrated en masse from Ruby/Python/Something else to
Go.

(Edit: not meant to be a political statement, more of a practical observation.
I only recently started using Go.)

~~~
jacquesm
That may be one of the bigger chances for go: mobile. After all being more
efficient on mobile translates into longer battery life and go potentially has
a huge advantage over the current java (ok, not java) based environment on
Android. For google this would be a triple win, get out of the Oracle mess
entirely, give their mobile developers a super fast toolchain and give the end
users better battery life.

~~~
swah
I love Golang, but its ain't very expressive, so it cannot be a good match for
writing UIs. And Swift is much closer to Rust than to Go, IIUC...

------
nickpsecurity
I appreciate you publishing this experiment as it will show Java's problems
for what they are. However, a real test of Go's safety and efficiency would be
a comparison to a similar language such as an optimized Wirth language, a
subset of Free Pascal (Delphi-style), typed LISP (eg Racket), Julia, or Ada.
People keep forgetting about the last one in safe, efficient, systems
programming despite it doing for a long time what Go and Rust hope to do
eventually. Its long-time use in embedded systems indicates it can be quite
efficient.

Regardless, Go certainly improves on the reliability of applications vs C++
while being much more efficient than .NET or Java.

------
melling
I've got a little Swift Language "search engine" that I built with Go on App
Engine. I haven't crawled any sites (yet). I simply created a Go data
structure to do in memory searches because I didn't feel like using Google's
data store.

Here's the site:
[http://www.h4labs.com/dev/ios/swift.html](http://www.h4labs.com/dev/ios/swift.html)

Here's the data:
[https://github.com/melling/SwiftResources/blob/master/swift_...](https://github.com/melling/SwiftResources/blob/master/swift_urls.tsv)

I'm approaching 1400 URL's and it's still snappy. I was hoping Go's claimed
"efficiency" would keep freely hosted a bit longer than Python.

~~~
akhilcacharya
>I'm approaching 1400 URL's and it's still snappy. I was hoping Go's claimed
"efficiency" would keep freely hosted a bit longer than Python.

That is exactly why I picked my Go for my latest side project.

I just hope the framework I'm using isn't the bottleneck, because I really
hate writing pure Go servers.

------
_JamesA_
Java's main feature is compile once - run (almost) anywhere. From embedded to
mainframe as long as a JVM is available.

How does Go stack up for cross-platform development? Does every application
and library have to be (re)compiled for the target platform?

What about support for alternative architectures (ARM, PowerPC, etc)?

~~~
xienze
Go does require recompilation for every platform, but I'll give them this,
it's very painless. Apparently in 1.5 you can just set an environment variable
for your architecture and one for your OS and you're good to go.

------
kentonv
> Resident memory usage dropped from 87MB down to a mere 3MB, a 29x reduction!

This isn't so much Java vs. Go as it is JIT/interpreted vs. AOT-compiled. The
numbers are entirely typical across a wide range of such comparisons.

With an interpreter or JIT, you need to load all your code at startup and
process it. Generally, _all_ of your dependencies need to be loaded and parsed
upfront, either converted to some internal in-memory representation or JIT'd
directly to machine code. This will allocate a bunch of heap structures during
the processing, and the end result is a bunch of data that needs to stay
resident and can't easily be shared with other processes.

With AOT, you mmap() in a file. The OS only pages in the code you execute, and
can page it back out as needed. Pages are shared between all processes running
the same executable.

At sandstorm.io our rule of thumb is that an app written in Node, Ruby,
Python, PHP, etc. will take 100MB of RAM while an app written in C++, Rust, or
Go will take 2MB. Since Sandstorm runs per-user (and even per-document) app
instances, this is a pretty big deal.

The good news is that [https://github.com/google/snappy-
start](https://github.com/google/snappy-start) _should_ fix this problem: by
checkpointing the process after it finishes its parsing/JITing but before it
starts handling requests, we can get an mmap-able starting state that is very
much like an AOT-compiled binary. At least, in theory -- there's still a bunch
of work to do for this to actually work in practice.

> The resulting docker image shrunk from 668MB to 4.3MB

While I would expect the Go image to be smaller (since Go builds static
binaries, so literally all you need in the image is the binary), I suspect
that the 668MB Java image was at least 90% unnecessary garbage that was not
actually needed at runtime. Unfortunately the package managers we all use are
not optimized for containers; instead they evolved targeting systems with
dedicated disks that can easily absorb gigabytes of bloat.

In Debian, for example, every package implicitly depends on coreutils. That's
perfectly reasonable when installing an OS on a machine: you almost certainly
need a working shell to boot and administer your machine. But a _container_
can get by just fine without coreutils, and a typical web server probably
(hopefully) doesn't need to call out to a shell. Even if a shell is needed,
busybox/toybox is probably sufficient and will take a lot less space.

Packages also often contain things like documentation, unit tests, etc. which
obviously aren't needed in a container.

For Sandstorm.io we deal with this problem by running the app in a mode where
we trace all the files it actually uses, and then we build a package
containing only those. It mostly works and manages to keep packages
reasonably-sized, but it does lead to bugs of the form: "I forgot to test this
feature while tracing, so the assets it requires didn't make it into the
package." We're looking for better options.

~~~
vonsnowman
> This isn't so much Java vs. Go as it is JIT/interpreted vs. AOT-compiled.
> The numbers are entirely typical across a wide range of such comparisons. >
> [...] while an app written in C++, Rust, or Go will take 2MB. Agreed. As
> mentioned in the blog post, I considered Rust but decided against it because
> of I found it much less mature than Go. I did not consider C++ because, as
> mentioned in the blog post, part of the point was to experiment with new
> language/tools and even though I consider myself proficient with it, I
> learned the hard way that the lack of memory safety is rarely worth it.

> I suspect that the 668MB Java image was at least 90% unnecessary garbage
> that was not actually needed at runtime. Unfortunately the package managers
> we all use are not optimized for containers Exactly. That was part of the
> point of this blog post, which I may not have been successful at getting
> across. Switching to go was, if not _the_ path of least resistance to solve
> this issue, at least one of a few relatively easy routes. It also happened
> to be a great deal of fun.

~~~
mwcampbell
I assume you didn't use the normal Dockerfile-based build system to build your
super-small Docker images for the Go-based services. So how did you do it?

~~~
vonsnowman
We're not doing anything too fancy. Basically, we spawn a container to build a
statically linked binary and do a regular Dockerfile-based build inside that
container. The result is an image which contains only a single binary (any
maybe some static assets like config files or images).

We're planning to open source our build script shortly.

------
ploxiln
I'm all for replacing java bloat with a little bit of go, but it seems like
the cause of the bloat becoming a real problem was hopping on the docker
bandwagon, for a collection of services that always run together in an
appliance and really benefited from being hosted in a shared JVM?

Isn't the JVM + servlet container thing supposed to be able to isolate the
different services? They get their own bunch of threads, and their faults
probably shouldn't crash other servlets?

~~~
eternalban
You should read Sun's J2EE specs. There is little semantic distinction between
a stateless session bean and a container hosted micro-service. The specs were
never fully grasped (imo) by the Java community and those who got it (per
gossip I heard) -- appserver vendors e.g. IBM, JBoss, etc. -- effectively
crippled the spec by resisting the completion of the APIs that would
commoditize their containers.

Sun was really ahead of the game in various fronts.

~~~
timtadh
So true. I had to read the entirety of the JSP spec (and a few others) when I
was an intern to help the company do some static analysis things. I also read
a good chunk of Tomcat. Sun had this grand vision of App servers which you
could just push code to and it would run completely isolated. The app servers
where supposed to be spec compliant meaning your app could run on any
implementation. But, and this is what bit the company I was working for, all
of the implementations add lots of non-standard bits and broke standard bits.
This meant that if you had written your app to go on WebSphere there was
essentially no way it was going to run on TomCat without modification.

If Sun had more tightly controlled the marketplace for these things I think
the whole ecosystem would have been more robust.

------
stesch
How tied is Go into Google? What if Google drops Go?

~~~
patio11
You're probably being downvoted for off-topicness, FYI, since this comment is
equally germane to any mention of Go. That said, I feel it is a comment in
good faith and deserves an answer.

Question #1: How invested should you model Google as being in Go's future?
Answer: _Extraordinarily invested._ They have a whole lot of code written in
it, most of which the world will never hear about, and which powers services
that they will continue running until the sun goes nova. Google will likely
continue maintaining and extending Go programs (as well as C++, Java, and
Python) for the foreseeable future.

Question #2: Can Go survive without Google's corporate backing? Answer: Go is
an OSS project. Like many OSS projects, it receives a substantial amount of
support from corporate interests. Go is not uniquely a Google priority -- many
organizations like having a systems programming language which has its feature
set. In the absence of meaningful support from Google, Go code existing as of
August 2015 would continue to function. Further versions of the
language/toolchain/etc would have substantial question marks about them, but
the community feels large enough that this would be a Significant Event rather
than a death knell.

Does that help?

~~~
stesch
I'm not sure if this will help me. I guess I'm in a programmer midlife crisis.
Every new thing is potentially a waste of time because you can't predict if it
is still around in 2 years. And with Google you know that they invest millions
of dollars in projects and then abandon them.

Would I be better off maintaining decade old COBOL projects? Sometimes I think
so. Other times I'm glad I can chose the technology I want to solve the
problems at work.

August 2015. 31 years since my first computer.

~~~
ansible
You can never stop learning. Go is my current 'thing', at least for personal
projects. But who knows what the landscape will be like in 5 years or 10.

For a while I though Haskell was the most awesome thing. Good Haskell code has
a timeless quality to it (in a couple senses of the word). But I found
adapting my thinking to it difficult, and it wasn't likely to be something I'd
use at work then or now.

------
mavelikara
I have a question on Go's performance that I'd like someone here, who has
experience writing programs in it, to help shed some light upon.

1) Go does not have a runtime. This means that there is no JIT to do any
optimizations based on runtime profiling.

2) Go is also designed to compile fast. Since it compiles fast, the compiler's
time budget to do compile-time optimizations is small and it probably can't do
the best job possible.

Are these two points accurate? If so, how does Go perform as well as it is
claimed to do? Where is the catch?

~~~
flippant
1) Go has a runtime that's included in the binary that you get when you run
`go build`. It takes care of garbage collection, goroutines etc. It does not
do any JIT compilation afaik.

2) Go compiles fast because it gives up a lot of modern features (namely
generics).

------
tapirl
I always think Golang is a Java killer, but I think Java itself is more a Java
killer than Golang.

------
umhan35
I hope that there is a compiled version of Scala.

------
findjashua
the only thing that's preventing me from jumping on the Go bandwagon is lack
of a nice collections library (a la lodash).

~~~
politician
That's due to a lack of generics. There are some workarounds like gonerics [1]
-- a clever abuse of import declarations.

[1] [http://bouk.co/blog/idiomatic-generics-in-
go/](http://bouk.co/blog/idiomatic-generics-in-go/)

------
aikah
I'll bite.

While it is absolutely true Go servers use less memory that classic servlet
deployments, The question is what were you using at first place? where you
using a big framework? with this or that big IoC container ? with a bloated
ORM ? ... or where you using barebone jdbc and writing servlets without any
framework? because essentially that's what you're doing with Go, Go has 0 big
framework(and no Beego or Revel are not complex), 0 big ORM , 0 IoC container
... And while the Java culture is about heavy decoupling and reusability , the
Go code culture is basically about writing correct code without thinking about
re-usability at all, because often you just can't. So I'm curious. My point is
didn't you reduce memory usage because Go forced you to write code a certain
way ?

~~~
jgalt212
> the Go code culture is basically about writing correct code without thinking
> about re-usability at all, because often you just can't. So I'm curious.

That's a very strong statement. Do you have evidence to support this? I don't
code in Go right now, but have been keeping an eye on it as it continues to
gather momentum.

~~~
dcsommer
Lack of generics can make it harder to write cleanly reusable modules in Go.
I've noticed gophers are often less allergic to copy pasting code with tweaks
(as long as it isn't too many lines) and don't mind rewriting similar code if
it is obviously correct. It was a bit of a culture shock for me at least.

~~~
_ak
You confuse parametric polymorphism with reusability. The former is merely one
of several ways to achieve the latter. The Go way for reusability usually
consists of interfaces.

~~~
dragonwriter
Interfaces and parametric polymorphism are not alternative approaches to
solving the same problem, which is why many languages that feature parametric
polymorphism also feature interfaces or similar constructs [0] (and why some
languages that had interfaces for a long time later _added_ parametric
polymorphism [1].)

[0] e.g., Haskell typeclasses

[1] e.g., Java

------
s73v3r
You know, as fun as it sounds like this was, wouldn't the natural solution to
the problem be to roll back the Docker rollout?

------
davexunit
And the cycle continues, from one crappy enterprise language to the next. I
don't who said it, but whoever said "Go is a bold step backwards" is spot on.

~~~
hwh
There are times when a step back is the mandatory step to get a new
perspective on things. Just sayin'.

~~~
davexunit
But this is a step back to the cold, dead, static systems of UNIX. How about
stepping back and taking a look at the dynamic, hackable environments of Lisp?

~~~
_ak
You should rather ask yourself why Lisp hasn't been able to attract the same
large and active community in 5 decades that Go has been able to attract in 5
years.

~~~
davexunit
Argument ad populum.

~~~
_ak
I'm not saying either of them is better because or the amount of people they
attracted. I merely ask why Go managed to interest more people than Lisp in an
order of magnitude of time less.

