
Another go at Go failed - scapbi
http://oneofmanyworlds.blogspot.com/2014/01/another-go-at-go-failed.html
======
stiff
I think there is more to learn here about engineering mistakes than about Go:

\- Why pick Go for this project in the first place? Those days the biggest
productivity difference that arises from language choice comes from the
availability of libraries, and it does not take much research to see that Go
wasn't particularly targeted at numeric computing and that library support for
those kinds of things is very poor. There is a number of mature platforms for
this class of problems, SciPy, MatLab/Octave, C/C++ with various BLAS-derived
libraries etc.

\- The bit on poor performance is unconvincing because the source of the
difference has not been identified. The speculations about Go and Java that
follow are so poorly backed by any evidence and so wild they should have been
cut out from the article. It's clear that the author has no clue what really
happens in either case, and he proceeds to draw conclusions anyway. This kind
of "magical" thinking about black boxes one doesn't understand is
unfortunately all too common across software engineering.

\- One place where I agree with the author is that Go's zoo of builtin data
structures is really, really poor compared to Java. I mean compare:

[http://golang.org/pkg/container/](http://golang.org/pkg/container/)

[http://docs.oracle.com/javase/tutorial/collections/interface...](http://docs.oracle.com/javase/tutorial/collections/interfaces/index.html)

[http://docs.oracle.com/javase/tutorial/collections/implement...](http://docs.oracle.com/javase/tutorial/collections/implementations/index.html)

~~~
jamra
This reminds me of that one guy on the go-nuts irc channel who asked for help
with his Ruby port over to Go. He was scraping a set of web pages in Ruby and
migrated that over to Go for its easy parallelization. His claim was that Go
was 3x slower in speed. He pasted some code that seemed fine, but left out the
context of what he was doing. At the end of the day, it as just an attempt to
claim that Ruby is faster than Go. If he doesn't provide the entire context
with benchmarks included, I'm just taking his word for it.

On another note, I built an algorithm using a bitset. At first, I used one of
the libraries the author linked, but then I saw that it was easier to just do
the bit-bashing myself for my particular use case. It's not that difficult if
you are familiar with C and C++ programming.

If, however, you are coming over from a language like Python, Ruby, and even
Java to criticize Go is an easy thing to do. Those are very high level
languages that protect you from needing to understand types. The object
oriented parts of Java languages give you the ability to use polymorphism,
which is not as straight forward in Go. You don't have a common base class.
You only have interfaces. Trying to recreate generic structures and then blame
the language for not having them is foolish. If you can't program without
generics, stick with Java from the beginning. Or better yet, don't do a
project in Go until you understand how to approach problems the Go way.

I happen to like Go for the very reason that you don't deal with generics.
Seeing the types make it easier for me to follow as opposed to following a
chain of inheritance. Getting rid of all the factory code trims my code down.
This makes things easier to read when you are not the author.

Comparing Java's compiler to any other compiler is going to have predictable
results. Java may have the best compiler out there.

~~~
pcwalton
Generics, inheritance, and the factory pattern are completely orthogonal
features. Adding generics would not entail adding inheritance, mandating the
factory pattern, or any other slippery slope feature.

~~~
stcredzero
Most of Go's feature decisions seem to have something to do with compilation
speed or how it fits in with the concurrency features and GC.

Inheritance is overrated, and the factory pattern is often overused. Both of
those happen with generics.

~~~
pcwalton
> Inheritance is overrated, and the factory pattern is often overused. Both of
> those happen with generics.

Generics have nothing to do with inheritance and the factory pattern. There
are lots of languages that have generics but neither inheritance neither
factories: SML, OCaml, Haskell, etc.

Inheritance makes generics _harder_ , in fact, because type inference becomes
undecidable in the general case.

Factories are basically a workaround for functions not being able to be
freestanding (unattached to a class) in Java (the "kingdom of nouns"), a
problem that Go doesn't have.

~~~
stcredzero
_Generics have nothing to do with inheritance and the factory pattern._

Where do I say such a thing? I'm saying that generics are both overrated and
overused.

 _Factories are basically a workaround for functions not being able to be
freestanding (unattached to a class) in Java (the "kingdom of nouns"), a
problem that Go doesn't have._

Being the "Kingdom of Nouns" is kinda the point of Smalltalk/Objective-C style
OO. (Though Alan Kay once famously said that when he thought of OO, he was
_not_ thinking of Java.) That said, while it is nice to have someplace to put
functions, there are times when it's also nice not to be forced to attach them
to a class. Not so sure it's a problem as much as it's just a particular
approach with its advantages and drawbacks.

Where do you get that Factories are "a workaround for functions not being able
to be freestanding?"

~~~
cstrahan
>> Generics have nothing to do with inheritance and the factory pattern.

> Where do I say such a thing? I'm saying that generics are both overrated and
> overused.

It _looks_ like that's what you're suggesting here:

> Inheritance is overrated, and the factory pattern is often overused. Both of
> those happen with generics.

\---

> Where do you get that Factories are "a workaround for functions not being
> able to be freestanding?"

A factory is, conceptually, a function of some set of inputs that returns a
new instance - which is, of course, exactly what a constructor is. Now, it's
not always appropriate for a class to know every single way in which it might
be assembled, so such responsibility is usually lifted out - the question is
where to put it. We already have constructors, and those are functions, so it
would seem reasonable that we could just write method similar to a
constructor, place it in some other namespace (perhaps in a completely
different package/module), and then pass that along to the component that
needs to create these new instances.

For languages like Java, the problem is that functions are not first class -
you can't directly pass along a method/function like (Conf -> SomeService), so
instead, it's common to create some special type, like SomeServiceFactory. If,
for comparison, you take a look at Scala/Haskell/C#/etc, you'll wont often
spot /.*Factory/ anywhere, because a function (with the ability to close over
free variables) is much more concise, and doesn't require defining new types
(e.g. SomeServiceFactory, versus Function<Conf,SomeService>).

I think that, seen in this light, the practice of defining dedicated factory
classes is a rather clumsy approach necessitated by the design of the
underlying language.

~~~
stcredzero
_It looks like that 's what you're suggesting here:_

 _> Inheritance is overrated, and the factory pattern is often overused. Both
of those happen with generics._

Non-sequitur here. To me, it's clear that I'm saying that generics are
overrated and overused. Your interpretation makes no sense!

 _For languages like Java, the problem is that functions are not first class -
you can 't directly pass along a method/function like (Conf -> SomeService),
so instead, it's common to create some special type, like SomeServiceFactory._

Another non-sequitur here. Factory pattern was originally popularized in the
GoF book as a way of providing an opportunity for polymorphism.

 _If, for comparison, you take a look at Scala /Haskell/C#/etc, you'll wont
often spot /._Factory/ anywhere, because a function (with the ability to close
over free variables) is much more concise*

Old hand at Smalltalk here -- over 10 years. You don't often see Factory
classes in Smalltalk. We also have very easy and nimble closures over
variables in the context they're defined. I still don't get what you're on
about.

~~~
Sssnake
>Non-sequitur here. To me, it's clear that I'm saying that generics are
overrated and overused. Your interpretation makes no sense!

 _You_ are making the non-sequitur. His interpretation is the only one that
makes sense. It is not clear at all that you are saying what you claim you are
saying. You are in fact not saying anything like it. You are saying two things
you don't like happen with generics, but that is completely false.

~~~
stcredzero
Okay, now you just sound like you're trolling. Please point me to the grammar
rule that says my referents can't be verbs.

~~~
Sssnake
What do you mean "now"? That was the first thing I said to you. You may wish
to consider that when many people are telling you that what you said was
nonsense, it may not be that all of them are crazy.

~~~
stcredzero
_What do you mean "now"? That was the first thing I said to you._

So you are trolling, and you still haven't pointed out such a rule.

------
sigmaml
Author of the blog post here. Some of the comments here suggest that I was
probably new to Go. Not quite. I was reasonably active in the Go community
(and on golang-nuts) in the first two years of Go's public life. Also, when
discussions of generics were taking place informally in the mailing list, I
was one of the first to have actually written at least a half-serious
`proposal' for generics (you can read it at
[http://oneofmanyworlds.blogspot.com/2011/11/draft-2-of-
propo...](http://oneofmanyworlds.blogspot.com/2011/11/draft-2-of-proposal-for-
generics-in-go.html)).

As for achieving `generic' code through static generation using an external
tool, I had had considerable success with it in some earlier projects. Except
that the number of types is much higher in this project, and things could not
be as simply - or clearly - generated statically.

I cannot publish the code because of the client's IP involved -- not because I
fear criticism; see, I was ready to face _this_ criticism :-). Those of you
who read my original post in golang-nuts may have already read that, of
course!

~~~
arnehormann
This is too late to help you, but still...

BitSets: look at math/big - not that intuitive, but what you need is probably
there.

Sets: I wrote
[https://gist.github.com/arnehormann/6234573](https://gist.github.com/arnehormann/6234573)
while thinking about an api. It's not a regular repository because I never
needed a set type myself, but it should work.

Like another commenter said, the cpu usage statistics in the Java program are
most likely due to Java threads you didn't start yourself, e.g. the garbage
collector. If your code involved creation and disposal of a lot of Objects, Go
is at a serious disadvantage compared to the JVM. But that can be mitigated
with a little effort and will probably disappear in due time.

~~~
kisielk
I actually wrote a bitset implementation using math/big:
[https://github.com/kisielk/bigset](https://github.com/kisielk/bigset)

------
RyanZAG
Who would have thought that a brand new language wouldn't have the features,
library support and optimization that the more popular languages have? Should
be obvious, but then you read through HN posts with people dismissing
languages like C++ and Java as 'too old' or something and that you need to use
some brand new untested language to be worth talking about.

Never select a language based off hearing about it on HN or blogs. Either
stick with what you know or use a tool that has very specific optimizations
for the problem you're going to tackle (and no, concurrency is not a good
option to jump off the JVM as it has incredible concurrency support already:
see [https://github.com/LMAX-Exchange/disruptor](https://github.com/LMAX-
Exchange/disruptor) for the fastest concurrent bus I've seen in any language).
Of course, there is nothing wrong with testing out golang or haskell - just
don't force your paying client to test it out with you or you might be one
less client shortly.

~~~
mercurial
There is nothing wrong with testing golang, certainly. But Haskell is 24 years
old. Hardly the new kid on the block.

~~~
RyanZAG
Haskell (and Lisp) will always be 'new'. Especially going by HN posts which
seem to think that Haskell is some brand new language created last week to
solve the problem of 'side effects' and in a few months time everyone will be
using it.

~~~
IsTom
Don't forget Erlang. For some reason a big part of HN thinks it's an unproven
technology.

~~~
nknighthb
I don't know of anyone who thinks Erlang is unproven. Lots of us think it's
weird and not worth using.

~~~
pjmlp
Yet, your mobile phone calls might be going through Erlang powered switches.

~~~
throwaway2048
And my multi kilobuck bank transactions may be powered by COBOL, but you won't
see very many developers lining up for that.

------
pron
When I first learned of Go I thought it had a very narrow use case. The
language is basically simplified Java (or a reinterpretation of Java), and
works on the same level of abstraction. It's not low-level like C/C++ or Rust,
and not high-level "productive" like Clojure. It seemed like Java sans JVM,
and as Java developers know, the JVM is the best thing about Java (some would
say its only grace). It lacks the JVMs runtime profiling and monitoring tools,
as well as the JVMs most powerful features of dynamic class loading and
runtime bytecode instrumentation. Its only advantages, as I saw them, were a
much reduced startup time and a lower barrier to entry for beginners; its only
use case, I thought, was for writing fast command-line apps. Most people who
seemed excited by Go were Python and Ruby developers who liked the speed boost
and the easy set up.

Now I think Go actually has some very good use cases. While I would never
dream of developing a large, complex or critical app on any platform other
than the JVM, the fact that Go produces self-contained executables makes it
very convenient sometimes. Fast command-line programs are actually not too
narrow a use case, and Go is not useful just for those. I can see myself using
it for other small web or network services as well. I still think Go is a JVM-
less Java, or a Java Lite, but apparently Java Lite is a very useful thing to
have.

~~~
barrkel
It's not very like Java at all. The only OO-like feature it has is interfaces,
which are more like Haskell's type classes combined with existential types
than anything else. (The resemblance here is actually very close,
implementation-wise: roughly, vtables at the per-instance level rather than
per-class level).

The other semi-interesting things it has are (a) channels + parallel functions
and (b) the return of error codes for error handling.

Java things it doesn't have start with reflection, bytecode (CPU
independence), dynamic runtime code generation, inheritance hierarchies,
generics, "everything is an object", array covariance, exceptions as an
idiomatic error propagation scheme, scoping based on nested namespaces, no
code outside of classes, nested types with scoping to match, inner classes
with implicit outer class self pointer, only value parameter semantics, and
only reference user-defined types.

In fact most of what makes Java distinct from the subset it shares with C is
missing, except for a garbage collector.

~~~
NateDad
Not sure if I'm reading your response incorrectly... but go has reflection.
I'm not sure what you mean by scoping based on nested namespaces.... Go has
similar scoping to pretty much every other modern language. Are you saying
java has no code outside of classes? Because Go has that (and doesn't have
classes).

Also... Go has OO features. You can make an object-like thing by tying data (a
struct) with behavior (methods tied to the struct). It doesn't have
_inheritance_ which is not the same as not having OO features.

~~~
barrkel
I think you think I'm criticising Go. I'm not. Beyond that, I think you
misunderstood my response.

------
silvestrov
_the CPU utilisation ... was around 370-380%! I was now totally stumped_

I guess that his code allocates a huge number of objects as all input and
output classes are final. The JVM's garbage collector is able to run
concurrently, so I guess it's the GC that takes so much CPU. AFAIK Go uses
mark-and-sweep collection which is very slow.

That would explain the unexpected difference in running time as the JVM's
garbage collector is very mature and fast.

~~~
NateDad
When Go is slow, it's almost always due to excess garbage creation. This can
usually be fixed by optimizing your memory usage... but I'm guessing an
experienced java professional may not think of that precisely because java's
garbage collection is so damn good most of the time.

~~~
yelnatz
I know theres a []byte mempool project on github.[1]

Still pretty early though, I don't think it can do dynamic sizes?

[1]
[https://github.com/thejerf/gomempool](https://github.com/thejerf/gomempool)

~~~
NateDad
Most of the time it's really just a matter of reusing data structures rather
than creating new ones and throwing them away immediately, over and over
again.

~~~
yelnatz
Yep, I think that's basically the idea there.

"You already have this []byte, don't throw it away, give it back to the pool
so you can reuse it."

------
Goranek
Seems that 2014 won't be a good year for Go on HN. Same old story as with Node
and Mongo. First they ignore you, then they praise you, then they hate you.

~~~
matthewmacleod
Those three steps are basically:

\- New technology is introduced. Nobody's really heard of it or used it, so
beyond a few "Look at this new thing!" articles, nobody talks about it.

\- The technology gets some penetration. New users pick it up, probably
because it solves some issue or irritation they have. They write about how the
technology helps to deal with it, or why it's interesting; if it
didn't/wasn't, they'd probably not bother using it, and would be pretty quiet
about the whole thing.

\- If the technology made it this far, there is an explosion in popularity as
more people pick up the tools and use the technology. Typically this results
in quite a few people using it in the wrong way, or because it's the current
'hot stuff' (rather than because it will solve a particular problem), or maybe
picking it up a little bit too early. Lots of these people will write about
how the technology sucks, or how it doesn't solve particular problems. That's
fine; it's the public knowledge-gathering phase, and although there will
inevitably be a lot of negativity, other people will discover the benefits,
and the technology will frequently evolve to address popular concerns.

\- The fourth step, that you didn't mention, is that the technology and
discussion around it becomes more "mature" \- it's widely-used, everyone's
more-or-less aware of the pros and cons. There will be the occasional post
called "X Sucks, I'm Moving to Y!" or "Why I'm still using X and not Y".

tl;dr: that's the way it goes - it takes a while for new technology to work
out the kinks and for the community to understand where and how it should be
used. And while that happens, they'll talk about it.

~~~
mseepgood
[http://upload.wikimedia.org/wikipedia/commons/9/94/Gartner_H...](http://upload.wikimedia.org/wikipedia/commons/9/94/Gartner_Hype_Cycle.svg)

~~~
Tegran
Once you've embedded the Hype Cycle in your consciousness, it's amazing how
often new technologies follow it. Also interesting just how worked up people
get at each peak and trough... :)

------
claystu
This is the kind of article we need more of on Hacker News.

The author chose a newer language to build a real project in and then gave us
an evaluation of how that language worked as a tool.

This is far superior to the typical benchmark-game blogs that try to compare a
few languages using only a small test program.

------
arundelo
_being able to do minus, union, intersection,_ etc. _I had to code those in-
line every time._

I'm not sure I understand the post author's complaint here. What's wrong with
writing your own SetDiff, SetUnion, and SetIntersection functions and doing
stuff like the following?

    
    
        baz = SetUnion(foo, bar)
    

(I have done very little programming in Go.)

~~~
NateDad
The problem is that you would need to rewrite that code for each type of foo
and bar.... so if you have a set of ints and a set of strings and a set of
SomeStruct... they'd all need their own implementation.

This is where code generation can work really well, especially for boring crap
like set functionality... but he's right that rewriting it each time you
figure out you have a new set type is a pain in the butt.

~~~
Roboprog
_If_ the base type of the set is a bit set, the function need only worry about
the position of each bit, and not the intended type. Of course, if the set has
content in hash buckets (or a similar scheme), you would need to pass in some
kind of comparator function/callback.

I say this as a former C programmer used to doing such things to make library
routines like "bsearch()" work.

Too many things in Java rely on subclassing, rather than functional
composition.

------
yelnatz
tldr: I will be using a lot of generics and do tons of set operations. I will
chose Go, a language that doesn't have generics and sets.

(I won't post the Go code for criticism, and I couldn't stand golang-nuts)

~~~
sixthloginorso
So... if you need any data structure other than an array, a hash table or a
channel, you should skip Go and find some other language? That's kind of
limited.

~~~
tptacek
No, the problem is that he needed Sets of many different kinds. It's perfectly
straightforward to implement data structures in Golang; it's just hard to make
them work for a variety of types simultaneously.

~~~
sixthloginorso
> it's just hard to make them work for a variety of types simultaneously.

That's sort of what you expect from any given implementation of a data
structure and its related algorithms, though I imagine that some specialized
implementations benefit from having them tailored to their concrete types.
Examples, anyone, please?

------
SigmundA
What struck me is how naive the author is when he notices multi-core usage in
a single threaded java program and proclaims: _I still do not know what is
going on inside the JRE as the program runs, but I am truly amazed by its
capabilities!_

Yeah it's magic, it multithreaded my code, or um I don't know the garbage
collector maybe?

------
maxk42
Anecdotally, I think that I'm noticing a trend wherein people coming from a
strong Java or C++ background (or other strongly OO languages) object to Go
vociferously (typically citing generics and a couple other pet peeves) and
people coming from dynamic languages (or other languages lacking generics)
seem to have no problem with it. I think it may be a matter of which paradigm
you're approaching Go from.

~~~
RivieraKid
Possibly.I regulary use both static and dynamic languages and lack of generics
was one of my biggest complaints. If it's a static language, I want generics.
If the language is dynamic I don't really care (although some dyn. languages
have generics).

~~~
maxk42
I thought it was a pain in the ass until I realized golang really does have a
sort of dynamic parameter:

    
    
        func test(myVar interface{})
    

will accept any type at all. You can then use Go's type switch or a call to
reflect.TypeOf() to invoke different behavior based on the parameter's type.
To my way of thinking, it's pretty simple.

------
tetha
I still smile when people get surprised by the performance of java. A bunch of
people remember the loud people yelling "Oh Java is really slow and sluggish"
while whispering "as long as you compare it to C++ with arbitrary optimization
time, in a good use case". Truth is, java can be darned fast if you want it to
be.

~~~
frou_dh
Java-based GUI applications often being ugly and sluggish perhaps unfairly
tainted the reputation of the language and VM.

~~~
pjmlp
Mostly because they were developed by programmers that failed to understand
how to proper use Swing.

It is incredible how, regardless of programming language and UI toolkit,
people still take the easy root and do heavy work on the UI thread. And don't
make proper use of widgets customization capabilities.

~~~
frou_dh
C# with the WinForms API is the only desktop GUI programming I've done and I
found both the process and results very pleasant. IIRC I was fairly well
behaved and used the "BackgroundWorker" in a few places :-)

------
porlw
Rather than storing data structures directly in the hashmap, I would store
them in an array and map the keys to array indexes.

Then the types of the hashmaps would all be the same (all map key->integer),
and I could develop reusable procs for each set operation.

~~~
willvarfar
Wouldn't that mean an extra level of indirection while dereferencing?

~~~
dded
Yes, but so does run-time generics somewhere along the line.

~~~
sepeth
Really? AFAIK, compiler creates those functions/classes from corresponding
generics (it is called templates in C++, and it really acts like template in
C++). Hence, they are compile time.

I believe, it is the same in Java, too:
[http://docs.oracle.com/javase/tutorial/java/generics/erasure...](http://docs.oracle.com/javase/tutorial/java/generics/erasure.html)

~~~
dded
Well, yes, compile-time generics are compile-time. That's why I said
"runtime".

~~~
willvarfar
Yes, but you are recommending he do that in Go, so by having an extra array
lookup you'd be further slowing down the Go program, which he says is 5x
slower than the Java program already.

------
zeroDivisible
Disclaimer: I use Java professionally on a daily basis and am learning Go in
my free time.

I totally agree with all the points which most of you make. Firstly, you
should almost never choose a language / technology which you want to learn
when you are being given paid contract task to accomplish. It might be
different at your full-time position, when picking new tool (after agreeing
with the rest of the team or people making decisions) might really be a viable
choice, giving you an edge in the end.

Beside that - if you're being paid by the hour, if you had been able to find a
client who is willing to pay you for you to learn new stuff - stick to them as
them as long as possible. Most of the clients with whom I had been dealing
with would just fire me or terminate the contract.

As for the performance - and I'm not defending Go here - with discrepancies
that big, I'd just assume that I don't know language and all of it's quirks
and it's just me not using it properly. I know that you might had spent time
profiling and optimising stuff, but sometimes the overall design of your
program might be violating some of the rules of given language, punishing you
with performance issues in the end.

(check
[http://www.techempower.com/benchmarks/](http://www.techempower.com/benchmarks/)
and the difference from first iteration to the last one, when people knowing
each framework tested started pushing their favourite toys to give them an
edge with misc optimisations)

From the two language which you had tested, Java was a way better choice here
- no amount of hype around a language should win over mature libraries which
were just suited for your job.

PS: and yes, I'd love to see generics in Go and can't understand any of the
reasons for no.

------
acqq
Note that the different readers in this discussion point out that the whole
"magic" of article writer's Java implementation being so much faster is most
probably the only thing that can run in parallel when you write the single-
threaded program: the JVM's garbage collector.

Which in turns means that the most of the "computation" performed is actually
the creation and collection of the always new objects, which people who ignore
the lower-level aspects of their programs consider being "zero-cost." Which is
not.

------
ceautery
There wasn't a good description of what overall task his program was trying to
do, or any source code showing how he approached maps, etc. Other than that,
it sounds like proof. Of everything.

~~~
MetaCosm
Also, it sounded like he was comparing single-threaded Go versus multi-
threaded Java?

~~~
mackwic
Go can't be really mono-threaded unless you are trying to do so (or your
program is really short).

A lot of the standard operations under the hood are in fact executed in
goroutines in a pool of threads. IOs are, for example. So you found yourself
gaining all the advantage of asynchronism without supporting the cost in the
code... exactly like this example in Java.

~~~
MetaCosm
[http://golang.org/doc/faq](http://golang.org/doc/faq)

Why doesn't my multi-goroutine program use multiple CPUs?

You must set the GOMAXPROCS shell environment variable or use the similarly-
named function of the runtime package to allow the run-time support to utilize
more than one OS thread.

Programs that perform parallel computation should benefit from an increase in
GOMAXPROCS. However, be aware that concurrency is not parallelism.

------
sigmaml
Author of the blog post here. Thank you all for your insightful comments and
critiques. A few points.

-> Several people have suggested that JVM's mature GC may be using other cores, resulting in the > 370% CPU utilisation. I admit that I do not understand the internals of OpenJDK's GC. However, I would like to point out that 100% of the roughly 1,200,000,000 statistics results instances created during one run are _not_ released until the program terminates. They are all stored in statistics results containers until the very end of the run. However, see below.

\- From a processing perspective, other than the manipulation of containers
and bit sets, almost all of the remaining processing is numeric. It is full of
integers and doubles getting added, subtracted, multiplied, divided, square
roots calculated, etc., as part of various statistical computations.

\- Where I needed sets was in preparing the several million working sets over
which processing iterations occur. Working sets are prepared based on user's
query criteria, several thresholds for filtering elements under a variety of
constraints, etc. From a garbage perspective, these working sets are the
biggest garbage generated during a run.

\- Go's numeric performance is certainly very good. I have had good
experiences with it in other projects.

\- It is true that I could not identify the causes to which the performance
differences between the Go version and the Java one could be attributed. Was I
being naive? Am I incompetent? Possible. As I concluded, this behaviour may be
obvious to more informed people, but it surprised _me_, and, that is what I
admitted.

~~~
zhenjl
Did you by chance profile the Go program to see where the hot spots are?

------
whizzkid
I still think that the way you are criticising the author is nonsense.

I totally agree that programmers need to use the right tool for the job but;

Most of the programmers will not know the core implementations of a
programming language when they started using it.(even after a couple of years)
This leaves them only one choice to decide if it can replace their primarily
preferred language or not. Trying out the language.

If it gives a bad taste from the beginning, doesn't ease the implementation,
or better performance, then programming language won't have much chance, will
not get attention and growing community.

This is why Ruby got a popular community with the help of Rails framework.
Developers found it very very easy to develop apps, it was very much readable
code, and you save lots of time in order to get the app up and running. This
advantages just made people ignore all the disadvantages of the language.
(concurrency, being hell slow, etc.)

As much as i want to try out Golang one day,code examples on internet doesn't
blow my mind like "wow, how smart that is!!"

------
dschiptsov
Of course Java is the best solution for any problem, who could dare to think
otherwise. It is mature, stable, incorporates millions of man hours (of solid
mediocrity) and there are no shortage in coders and believers.

[http://chrisdone.com/posts/dijkstra-haskell-
java](http://chrisdone.com/posts/dijkstra-haskell-java)

~~~
sixthloginorso
It has a state-of-the-art Virtual Machine, rich concurrency facilities (why
does everyone forget this?), reasonable type safety, great tooling, and it
operates within a diverse ecosystem of languages using the same
infrastructure.

But yeah, I have always liked the argument of throwing a curve ball at the
kids who were already programming in imperative languages. It also levels the
playing field and those who hadn't had any prior experience tend to perform
better without feeling so inadequate next to their peers.

~~~
dschiptsov
Rich concurrency facilities based on pthreads and murexes provided by an OS,
so no miracles here, just the same broken by design stuff.

~~~
sixthloginorso
Care to expand? I still find that Java's are some of the best concurrency
libraries you'll find, among imperative languages or otherwise.

------
patrickaljord
That's ridiculous, we get articles complaining about the lack of generics in
Go daily now. That's like complaining about the lack of type safety in ruby.
Go warns clearly that it doesn't comes with generics. Need generics? Use
something else, we all know Go doesn't have them. Nice way to get on the HN
front page though.

------
SideburnsOfDoom
> Russ Cox' original formulation of the now-famous tri-lemma is incomplete at
> best.

Could someone give a brief introduction to what this sentence means? I have
absolutely no idea about any of it.

~~~
signa11
probably this:
[http://research.swtch.com/generic](http://research.swtch.com/generic) ? go
had 3 options for implementing generics:

1\. leave generics out : the c way (slows programmer)

2\. do it at compile time: c++ way (slows compilation)

3\. box/unbox everything implicitly: java way (poor perf)

~~~
SideburnsOfDoom
Hm. Which of these does C# use? Which does Haskell use?

~~~
pjmlp
Regarding C# it depends on which compiler you talk about.

Microsoft's current JIT/NGEN, generate a single version for reference types
and a separate version for each value type. So a mix of Java/C++ approaches.

Not sure what the new JIT/NGEN compilers, RyuJIT will use.

I also don't know what approaches are taken by Mono, Bartok and IL2CPU, but
they might be similar.

~~~
SideburnsOfDoom
Yep, now I can see why this is trilema is "incomplete at best" \- c# and other
use what can be described as a mixture of these three approaches.

I was going to say that the c# compiler is fast enough despite this, but then
I remembered that one of go's selling points is that the go compiler is
blindingly fast compared to languages such as c#. Perhaps maintaining that
performance with generics is a real issue.

~~~
pjmlp
Although any language with modules is fast enough, compared with C and C++.

Many old timers like myself can remember the blazing fast compile times of
Modula-2 and Turbo Pascal compilers in MS-DOS systems.

Go compilers also lack a strong optimizer, which is tends to slow down
compilation.

------
Almaviva
Am I the only one who thinks writing my own Set data structure (based on a map
under the hood) isn't crazy at all?

~~~
frou_dh
If you're not the only one then you can all meet up in a month and each point
out bugs in the other n-1 implementations.

~~~
Almaviva
Does a set do so much that you'd be worried about doing it wrong? Not to say
having it in a common mature library wouldn't be an advantage, but it's
something I'd be pretty sure I could implement and get right the first time.

I'd be more worried about having two programmers write two implementations in
the same project with subtly different interfaces, and having different parts
of the code use each one. This is a cost and maintenance problem, but that's
also a social and communication problem common to all projects.

~~~
frou_dh
Yeah, I was exaggerating a bit, but yes I think there could be room for bugs
depending on what more involved operations are offered beyond basic membership
tests.

Anyway, have you seen the map[T]struct{} idiom for Go? Decent enough for the
basic case.

------
osteele
My rule of thumb is to use a language for something a domain that its
community uses it for. Python for scientific programming, Ruby or nodejs for
web servers, PHP for embedding dynamism in a static site. Then you're more
likely to find libraries and support, and to find adoption for your own
libraries and pull requests.

This doesn't mean you're always safe even on a language's home turf (Rails and
Node each had significant problems as a server platform for their first,
hyped, years), or that it's never worth stretching the domains that a language
is used for (that's where Ruby's Rails and Python's Numpy _came_ from), but
you should recognize that you're out on a limb when you do so.

~~~
okpatil
>Ruby or nodejs for web servers You haven't tried go, have you?

------
michaelwww
Note to self: don't try to foist an unfamiliar language on a client without
actually knowing if it will solve the problem efficiently.

------
_pmf_
> However, considering the fact that statistics instances are write-only, I
> hoped that Go could help me make the computations parallel easily[1].

I'm actually dizzy from shaking my head too much while reading this.

------
bwilliams
$GOPATH is my biggest issue with Go. I'd much rather have some sort of config
file than have Go determine anything from my project path.

~~~
baq
i had my reservations too, but then somebody told me that GOPATH is like a
virtualenv for python and then everything was nice again.

~~~
bwilliams
I'm not a Python user so I can't really compare. I still don't agree with it
since it forces longer paths to get to your project, and I wouldn't really
call it isolated.

------
mediocregopher
The author says go doesn't have generics, and he had to rewrite the same set
operations for each type that he used. Would this not work?

[https://gist.github.com/mediocregopher/8319986](https://gist.github.com/mediocregopher/8319986)

The items in the sets don't even have to be the same type

------
platz
I thought Haskell did not have issues with circular data type construction
with its 'tying the knot'

[http://www.haskell.org/haskellwiki/Tying_the_Knot](http://www.haskell.org/haskellwiki/Tying_the_Knot)

------
lafar6502
I'm not sure what can be said about qualifications of a programmer who doesn't
know how many threads does his program run and why. And this is in Java, where
the author says he's proficient. There's nothing difficult in checking how
many threads are there instead of speculating on some unclear link betweeen
'final' keyword and multithreading. It's quite possible that bad performance
is a result of poor implementation, not a fault of Go runtime. Unfortunately,
there's no code to have look at.

------
mratzloff
A Go templating project was posted here the other day: gotgo[0]. I haven't had
a chance to use it yet, but it may alleviate some small amount of pain.

As for poor performance, that is almost certainly a result of rampant object
creation, rather than reuse. Not sure how much of his program was concurrent,
how sophisticated it was, etc.

Ultimately if the data set fit in memory, Python would probably be the
appropriate choice for this kind of computation.

[0] [https://github.com/droundy/gotgo](https://github.com/droundy/gotgo)

~~~
pjmlp
> A Go templating project was posted here the other day: gotgo[0]. I haven't
> had a chance to use it yet, but it may alleviate some small amount of pain.

Replicating the C++ code generation tools of the mid-90's when templates were
started to be discussed at ANSI/ISO.

------
facorreia
For fast execution of parallel processing over immutable data, I believe Scala
would be an adequate choice. It would be a plus that it runs on the JVM and
can easily interoperate with Java code.

------
yanatan16
This guy needs to take a hard look at interfaces. Go didn't abandon generics,
they just told everyone that interfaces are a better solution. You can write
your code once as long as its formulated for interfaces.

As for sets, why not use a custom data structure like a balanced binary tree
(such as a red-black tree)?

~~~
xordon
BitSets have efficient set operations, eg: set intersection => bitwise AND,
etc.

see also:
[https://github.com/kisielk/bigset/blob/master/bigset.go](https://github.com/kisielk/bigset/blob/master/bigset.go)

------
nodata
tl;dr chose wrong language for the task.

~~~
baq
there seems to be quite a few people suggesting that go is the correct choice
for every task. the article is a sorely needed voice in the HN echo chamber.

personally i'm waiting for rust, go is nice but not better enough than python
to justify switching - especially when you consider maturity of third-party
libraries.

~~~
belluchan
> the article is a sorely needed voice in the HN echo chamber.

> personally i'm waiting for rust

See, this seems weird to me because Go is actually a language that you can
build nice things with right now. Check out coreos's etcd[1] for example.

Rust on the other hand gets a lot of adulation in this echo chamber but is so,
so far from completion that you're going to be waiting like a decade or so
before you can do anything networking related with it. And personally the
varying clumsy degrees to do the same thing many different ways in Rust (the
various boxing and unboxing and other memory handling options) are a real turn
off.

Comparing Go to Java is fair, and of course Java will come out on top given
its maturity, but Go offers a lot of good things. Comparing Go to Rust is not,
Rust is not ready for any kind of real world use.

[1] [https://github.com/coreos/etcd](https://github.com/coreos/etcd)

~~~
Dewie
What is really weird is how often Go and Rust are compared, period. Their
designs seem to be different in almost all ways and, as you say, they don't
even coincide when it comes to maturity.

~~~
belluchan
Not even that, but you can't compare the main devs with Go to Rust in terms of
personal accomplishment. Rob Pike who made an entire operating system at Bell
Labs and has published quite a bit. Every programmer should go read Rob Pike's
regular expression parser, that he wrote in like an hour and is published and
annotated in the book Beautiful Code. Brad Fitzpatrick who made memcached,
openid, and uh LiveJournal, Russ Cox also from Bell Labs, and many others.
It's an all-star team operating under Google's demanding auspices in an ivory
tower of unfathomable wealth, servers, needs and technology. These guys aren't
novices, they're not going to make a shitty programming language. If you are
unhappy with some part of Go (as I am actually, I'd like interfaces to know
about properties as well as methods but maybe that's weird) they've probably
thought about it and have a good reason for whatever choice they made.

~~~
4ad
You forgot Ken Thompson, inventor of Unix.

------
midas007
I'm really missing Erlang's awesome binary structure bit-
parsing/matching/twiddling.

IMHO golang is extremely orthogonal, that it tries to live to an ideal instead
of being most practical (ie generics).

btw, folks should give Elixir a shot (pun intended).

------
Kiro
Ok, so this is OT but can someone explain generics and their purpose LI5?

~~~
bstamour
It allows you write code that works for multiple types. For example, consider
the following function in C++:

    
    
        template <typename T>
        T min(T a, T b)
        {
            if (a < b)
                return a;
            else
                return b;
        }
    

This code works for any type T (ints, strings, floating point numbers) that
can be compared with less-than. In a language like Go that does not support
generics, you would have to write a min function for ints, a different min
function for strings, etc.

~~~
Roboprog
Keeping in mind that in C++, "<" would need to be an overloaded operator
defined by any type used for T. That is, to those of us non-C++ programmers,
there is a function call (callback) dependency hidden in that templated
function.

Not saying it's a bad thing, just that most other languages would show
something like "a.compare( b) < 0" to do something like this.

~~~
adrianmsmith
True, it's hidden, but the compiler will only compile code which uses that
function for types which meet that condition. So yes it's hidden, but at least
you'll find out about it at compile-time, not run-time, so it could be worse.

------
bdamm
In the comments he reveals that he didn't use channels. I think that's proof
that he was writing Java code in Go syntax, which is not going to work out
very well.

------
puppetmaster3
You get a D in programming. (get it?)

~~~
eonil
Unfortunately, D's coroutine support isn't stable like Go's one. It has
unclear stack size limit, it was simply impossible to me to make a robust D
program which uses coroutine. (please correct me if I am wrong.)

~~~
puppetmaster3
When I code, my goal is not to find a problem that I can apply a solution on.

------
corresation
_" The general attitude in Go community towards generics seems to have
degenerated into one consisting of a mix of disgust and condescension,
unfortunately."_

I think this attempts to make the practical state of generics in Go into some
sort of religious disagreement, which is unfortunate, as that isn't the case
whatsoever.

Whenever the topic of generics come up, the prevailing sentiment is that they
would be _great_ , but that the Go creators have some implementation
difficulties and some competing goals that make it impractical at this time. I
don't believe I've ever seen anyone of consequence in the Go community treat
generics as anything other than "would be _really_ nice".

It is a gap in Go and is widely treated as one.

Go absolutely needs more robust collection types, however. Total agreement on
that.

~~~
fauigerzigerk
It's not a religious disagreement between the Go team and those asking for it.
The Go team has simply stopped talking about it. But the reactions by the
community to people bringing up generics on golang-nuts has become outright
hostile.

~~~
corresation
That is more about group decorum than any technical debate.

Generics have been discussed to death regarding Go, and there is a long and
complex history of the choices and realities in Go. So it is understandable
that people can get a little irritated when someone stumbles in and declares
that maybe Go should add generics, usually then decorating their claims with
lots of exaggerated hysterics (most recently that Go is an "embarrassment"
because it lacks generics. Quite the accolades for the people who work long
and hard on it).

~~~
fauigerzigerk
Refusing to debate the issue is not understandable at all, especially because
the Go team has not rejected generics on principle.

The most popular response to any language debate seems to be "it's not a
problem in practice", implying all critics just "stumble in" and don't know
what they're talking about.

~~~
kkowalczyk
They are not refusing to debate.

They have debated this many times over in the past.

What they don't do is repeating that debate every week. It would take a lot of
their time and is largely pointless (in the sense that person that starts the
debate with 'go sucks because it has no generics' will not be convinced that
it was the right (or at least practical) decision to make regardless of how
cogent your arguments are).

~~~
fauigerzigerk
I don't want to force anyone to take part in a particular debate if they feel
they have nothing to add. But not taking part in a debate and denigrating
those who do want to debate an issue are two very different things. It's the
latter that irks me.

~~~
magicalist
Well, a good example is that we literally had the golang generics conversation
on HN yesterday. Forum goers are not machines; fatigue can easily set in. What
can be perceived as hostility to those who desire debate can just as easily be
people who are tired of the same "debate" over and over again.

That said, that's when a community should write up an faq[1] and then simply
point to it in a polite way that avoids engaging in the same conversation
again while still being welcoming to people thinking of joining that
community. If people aren't doing that, it's somewhat understandable, but long
term the acrimony can be poisonous.

[1] [http://golang.org/doc/faq#generics](http://golang.org/doc/faq#generics)

~~~
fauigerzigerk
The FAQ merely states that generics remain an open issue. That doesn't replace
a debate about it. On the contrary, it shows why a debate is necessary.

I fully understand that the Go team and long time forum dwellers are not
inclined to discuss the same generics proposals over and over again. So don't!

New ideas should be welcome though.

------
poorelise
I think in many cases you don't need generics because you can use the
interface mechanism instead. The way Go does it is a bit confusing at first,
so I suspect many Go newcomers don't really understand they could have used
it.

As an example look into the way sorting is implemented in the standard
library: [http://golang.org/pkg/sort/](http://golang.org/pkg/sort/)

I had to look at this example for a long time to get it... And now I have
forgotten it again since it was months ago :-(

I still thought it requires too many lines to sort stuff, but it is doable.

~~~
frou_dh
That's effectively subtype polymorphism, while generics are parametric
polymorphism. Many languages (including Java) make use of both.

------
asdasf
His dismissal of haskell is rather misinformed. Haskell has no such problems
with cyclic data structures. And this:

>Except that abstracting things into functions that take the `old' graph as
input, and answer the `new' graph as output are not very convenient or easy.

Is just crazy. Yes, it is very convenient and easy:
[http://hackage.haskell.org/package/mtl-2.0.1.0/docs/Control-...](http://hackage.haskell.org/package/mtl-2.0.1.0/docs/Control-
Monad-State-Lazy.html)

