
Problems with Go's design - lladnar
https://medium.com/@tucnak/why-go-is-a-poorly-designed-language-1cc04e5daf2#.pr6pifnky
======
cs702
While the title is linkbait-ish, the article makes interesting points with
code examples, and the author is not 'religious' \-- he concludes by saying he
will continue to use Go.

Like most other languages, Go is neither great nor bad; it's just another tool
designed by people to solve a specific set of problems -- in Go's case, people
who in the past have had to develop very, very large, complicated systems with
lots of concurrency. For projects like that, Go would be a great choice; for
other projects, it might not be.

In some circumstances even Ruby can be a better choice than Go for high
concurrency. I recently read a post on HN in which the author (someone with an
Erlang background) lays the reasons why he chose Ruby for a highly concurrent
application. When I first saw the link, my immediate thought was, Ruby!!?? But
then I read the post and the reasons were all very sensible and practical-
minded, so in that case Ruby was arguably a much better choice than Go,
Erlang, Scala, Rust, and the like.

Here's the post:
[https://news.ycombinator.com/item?id=10394450](https://news.ycombinator.com/item?id=10394450)
(direct link: [https://github.com/rustyio/super-imap#why-
ruby](https://github.com/rustyio/super-imap#why-ruby)) -- I really liked the
rational, practical, 'non-religious' tone.

Suggestion: don't call Go or any other popular language "poorly designed" with
a short blog post. Instead, say "it doesn't fit my current needs."

~~~
RodericDay
> don't call Go or any other popular language "poorly designed" with a short
> blog post. Instead, say "it doesn't fit my current needs."

that's not what the author wanted to say though. very, very often someone says
"this is bad" when they actually mean "this doesn't fit me". in this scenario,
I think the author made a very good case for "it's poorly designed".

~~~
cs702
RodericDay:

Language design decisions by superstars like Robert Griesemer, Rob Pike, and
Ken Thompson (the creators of Go) that may seem inconvenient or annoying when
working on small to mid-size projects could very well make life much easier
when working on giant projects which take years and do not fit on any single
person's head.

I'm reminded of this insight by Lawrence Kesteloot of Dreamworks: "What’s
particularly hard is having technical discussions with someone who hasn’t
broken through as many walls as you have. Breaking through these walls means
making different trade-offs, and specifically it means making a decision that
seems to make less sense in the short term but will help later. This is a hard
argument to make—the short term advantages are immediately demonstrable, but I
can’t convince anyone that a year from now someone may make an innocent change
that breaks this code."[1]

Unless you personally have led Internet-scale mission-critical software
projects at a place like Google, as the authors of Go have, I don't think
you're in a position to judge their decisions too harshly. Neither am I, BTW.

\--

[1] [http://www.teamten.com/lawrence/writings/norris-
numbers.html](http://www.teamten.com/lawrence/writings/norris-numbers.html)

~~~
spion
I keep seeing this argument all the time. Lets put a counter-argument-by-
authority: Fran Allen [1] thinks that the C was a huge step backwards in
language design [2], and there is no reason to think that Go didn't repeat the
same pattern.

Interestingly, the article you quoted mentions functional programming and
immutable data as the step to go from 200K to 2M lines. Go is fundamentally
incapable of functional programming* and its builtins allow pervasive mutable
state.

[1]:
[https://en.wikipedia.org/wiki/Frances_E._Allen](https://en.wikipedia.org/wiki/Frances_E._Allen)

[2]: [http://www.amazon.com/Coders-Work-Reflections-Craft-
Programm...](http://www.amazon.com/Coders-Work-Reflections-Craft-
Programming/dp/1430219483)

* Its impossible to support FP without generics. Even the most basic higher order functions require type variables.

~~~
ngrilly
The guarantees offered by functional programming and immutable data are great,
but they mostly evaporate when you move from a single process application to a
multiple processes system, distributed on many machines and communicating
through IPC.

Are you aware of a 2M lines code base that fully relies on FP and immutable
data?

~~~
deepnet
I beg to differ: the guarantees functional programming and data immutability
offer are exactly the sorts of guarantees needed for scalable parallelisation.

LOC is not a useful metric for the utility of a program, in fact the reverse
is true in terms of maintainability and places for bugs to hide.

This chap claims to write very robust programs, entirely functionally that are
worth billions in their operation.

[http://logicaltypes.blogspot.co.uk/2015/08/pure-
functional-p...](http://logicaltypes.blogspot.co.uk/2015/08/pure-functional-
programming-claims-irl.html)

~~~
ngrilly
I agree that "the guarantees functional programming and data immutability
offer" are very useful for "scalable parallelisation".

But this is not what I was answering to.

I was answering to the idea that FP and immutability are useful when you scale
from 200K to 2M lines of code:

> the article you quoted mentions functional programming and immutable data as
> the step to go from 200K to 2M lines

In my opinion, this argument is irrelevant.

~~~
deepnet
The argument being that non functional programming has fundamental limits to
its scalability, seems like a very important question as the complexity of
code begins to grow exponentially.

Large imperative codebases are inherently fragile, hence the need for test
driven development - good batteries of tests offer demonstrable reliability.

Functional programming offers provable reliability.

Provability is not just for scaling complexity but also for much simpler
software that absolutely must not fail.

Imperative code becomes hard to reason about before 200K LOC is reached.

~~~
ngrilly
The counterargument is that very large codebases tend to be composed of
multiple services. Each service lives in its own process and maybe in its own
machine, and communicate with other services through IPC. At that point,
you've lost the benefit of functional purity and immutability, because each
service can maintain some "hidden" state.

You're right, above some threshold, it becomes hard to reason about imperative
code with mutations. Your preferred solution is to adopt functional
programming and immutability. Another solution is to decompose your system in
multiple communicating services. Google's codebase is a very well known
example of the latter approach.

~~~
spion
This is false. Well, it may be true in Erlang, but its false in Haskell, where
there is always clear separation between equations and effects/state no matter
the source (IO to other services or local state). Not to mention that there
are tools such as STM that let you deal with state in a much safer and less
error-prone way.

Separating the state between multiple communicating services is basically the
same strategy as OOP (objects that communicate via messages and encapsulate
state) but with stronger encapsulation requirements (access only via API, you
can't just "reuse" methods willy-nilly all over the place but you have to come
up with a sensible library or a third service, etc etc).

It works, yes but it works about just as much as OO does. Which is... not very
much. And it also comes with its own tradeoffs (good luck getting atomic
changes over multiple microservices)

------
YZF
I actually had a subtle bug caused by variable shadowing. The current
behaviour of := is error prone and IMO should be revisited. The situations
where it cleans things up are offset by situations where it doesn't work
(including in compound statements where it often ends up being I'd like to
declare and check err but I also want to be able to use the other variable if
err==nil).

Another thing not mentioned is type switches, that feels like something that
was duct taped onto the language. I think it would have been better to be able
to use .(type) anywhere (e.g. in an if statement) and not have some sort of
special switch statement. So make types more of a first class thing. It's
obviously more work though but there is probably some middle-ground there that
would make it seem less like a hack.

I think the behaviour of slices is reasonable given that they are not as high
level as they are in some other languages. They're basically a slightly nicer
facade over pointer arithmetic and they are designed for efficiency and
performance. I think overall they're fine. The "..." is a little awkward
(appends could be a little nicer).

Just use goimports to and you won't see unused import errors any more. Works
for me and makes things cleaner.

All in all I think there are some rough corners that could use a little polish
but that can still happen, it's a new language after all. It's good enough to
be really useful.

~~~
echlebek
The behaviour you are talking about isn't anything to do with :=. It's just
how scoping works in Go. := is just syntactic sugar.

[http://play.golang.org/p/bh6pm_8s9S](http://play.golang.org/p/bh6pm_8s9S)

~~~
YZF
Probably the root of the issue is that it's slightly more complicated than
syntactic sugar:

"Unlike regular variable declarations, a short variable declaration may
redeclare variables provided they were originally declared earlier in the same
block (or the parameter lists if the block is the function body) with the same
type, and at least one of the non-blank variables is new. As a consequence,
redeclaration can only appear in a multi-variable short declaration.
Redeclaration does not introduce a new variable; it just assigns a new value
to the original."

I.e. the mix of declaration with re-declaration. I agree it doesn't seem like
much but it ends up causing needless confusion. If there was a more explict
way of doing this, e.g.:

x, var y = 1, 2 // y explicitly declared

maybe that would be better. not sure.

~~~
bkeroack
This is what enables the idiom "foo, err := DoSomething()" where err is
declared previously.

Without the mixed declaration/redeclaration you'd have to either declare a
different error variable every time in the block, or explicitly declare your
result variable:

    
    
      foo1, err1 := DoSomething()
      foo2, err2 := DoSomething2()
      // or
      var Foo foo
      var err error
      foo, err = DoSomething()
      foo, err = DoSomething2()

------
Jemaclus
Nailed it. I love Go, but all of the things listed in this article (and more)
make me bash my head against the wall more often than I'd like to admit. That
said, there are some fantastic things about Go that aren't listed in the
article (I feel like gofmt changed my life).

Don't let this article discourage you from investigating Go as a tool to use!

~~~
spion
I've never understood this, every Go user swears on gofmt for some reason that
I just dont get. Can you elaborate how gofmt changed your life? Its a really
simple tool and lots of languages have those...

~~~
Jemaclus
You're right. There are other tools out there. But what I really appreciate
about gofmt are a few things:

* It's highly opinionated. It's not cluttered with customization options. This means your Go program and my Go program are formatted exactly the same. Period. I don't have to choose between spaces or tabs or get annoyed that you chose spaces when tabs are clearly superior. * By being highly opinionated, Gofmt just takes care of those decisions. You focus 100% on coding -- not on stylistic decisions. * It's practically built in and maintained by the core team. The "other tools" out there are usually open-source. You have to go hunting for them. Gofmt ships right with Go. Then you have to figure out how to run them. With go, it's just a simple `gofmt <file>`. Boom. Done. No NPM dependencies, no Ruby gems to install. Just run it and move on.

I don't write Go full-time, but I've started adopting similar tools for my
primary languages. My editor at my current job runs a similar tool for Node. I
don't have to think about style any more. It's just taken care of for me. And
all of my team have reached the same conclusion. Peace of mind and focus on
what really matters is invaluable.

~~~
spion
The reason I don't get it, I think is that I've never cared about stylistic
decisions, ever. Why would anyone care, I have no idea.

I can configure my editor for either spaces or tabs. I run npm install when
starting with the project anyway, and it will also fetch any devDependencies
for me (which means a script such as npm run stylecheck can be made
available). The project lead decides the rules. Or there can be no style
rules, it doesn't matter - most of those are very superficial and have little
to no effect on anything.

~~~
Jemaclus
You obviously don't work with a team, or you work with a team that also
doesn't have opinions about style. That's _probably_ not a great thing. The
tab-vs-spaces debate is very real, as well as things like whether hanging
commas or trailing spaces are allowed, or whether you put one-if-blocks on one
line or if you have to split them up into multiple lines, or whether the
opening bracket goes on the same line or the next line, or whether... I could
go on. All of these are things people tend to have preferences for, so when
you work with multiple people, having a consistent style is a huge benefit to
reading other people's code.

Imagine a simple CSS example: Some people like to do one line per element,
while others like one line per style:

``` a { font-weight: bold; color: blue; text-decoration: none; } ```

vs

``` a { font-weight: bold; color: blue; text-decoration: none; } ```

That's a pretty trivial example, and for many people, both are acceptable. But
when you get into large projects with hundreds or thousands of styles, or you
have to code review that one change that was made off-screen on a really long
line of CSS, one of those styles is going to be more conducive to code reviews
and readability. Stylistic concerns are very real, and gofmt largely makes
those go away.

Like kyrra said, you may not be opinionated on the matter, but other people
are, and gofmt, et al, completely remove that concern from the table.

~~~
spion
Like I said, other code reformatting tools exist, the team lead picks the tool
and tool settings, and that should be the end of it.

~~~
sacado2
I have already used one such tool for C++ in one of my teams (aastyle ?
Something like that). It's only the firs step. Then you have to
wonder/discuss: what actual style to use? There are many C/C++ styles out
there (stroustrup, linux, gnu, OTBS, etc.), so you have to discuss about that.
Now, when you have chosen one, you have to discuss about minor fixes: "ok, so
OTBS is cool, but what about line lengths? Should we choose 80 cols? That's
silly, why not 120?" etc. All in all, you end up taking a whole hour (even
more) about this issue.

With go, that doesn't happen. You call gofmt and you're done. Another side
effect: when you get external source code (open source, code written by
another team, etc.), you know it will be formatted exactly the same way as
yours.

~~~
spion
I'm afraid that may be your fault. What style you pick doesn't matter much
(consistency does though) so you should just pick one.

It really baffles me that anyone could spend so much time on something like
that. I'm sure there are lots of more exciting (or more pressing) problems to
solve on the projects you're working on...

------
shawnps
I'm surprised to see the author mention not being able to compile when there
are unused imports. Editor plugins that call goimports have solved this
problem for a long time now. For example, I use vim-go
([https://github.com/fatih/vim-go](https://github.com/fatih/vim-go)), and if I
remove the only line of code that references the "fmt" package, the "fmt"
import line at the top of the file will automatically be removed.

Edit: Here is the reasoning on the FAQ behind code with unused imports not
compiling:
[https://golang.org/doc/faq#unused_variables_and_imports](https://golang.org/doc/faq#unused_variables_and_imports)

~~~
yokohummer7
This is a typical instance of solving language issues with excessive tooling.
I find it uneasy that we will be reproducing all the baggage Java required us
in a different language. And even Java didn't have mandatory imports.

~~~
shawnps
I personally wouldn't call it excessive. It's more like set it once and forget
about it. And it's something that basically all professional Go developers do,
along the same lines of how everyone runs gofmt.

------
Jabbles
Meh.

1\. How often do you insert into a slice? You know that's a O(n) operation,
right?

2\. nil is typed, I'll grant that it's not the most obvious part of Go's type
system.

3\. Meh.

4\. This is type covariance. It's complicated and hard to get right. The Java
Generics FAQ looks like this:
[http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.ht...](http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html)

5\. I like by-value loops. Everything else in Go is by-value.

6\. Yeah, fuck everything we know about parsing, let's make whitespace
significant, then we can declare slices like:

    
    
        x := []int{
          1
          -2
          +3
        }
        len(x) == 3
        y := []int{1 -2 +3}
        len(y) == 1
    

7\. Meh

~~~
pcwalton
That's not type covariance. Variance only comes up when you have generics,
which Go doesn't, and subtyping, which Go doesn't really have. It's the lack
of a coercion/conversion between slice-of-T to slice-of-interface.

The correct language-level solution to #4 is to introduce generics and to
allow generic type parameters to have interface bounds. That would solve the
problem without having to introduce variance.

~~~
Jabbles
I don't see how it's not type covariance.

Go's slices are generic to the extent needed, and the subtyping of Go's
interfaces fits the requirements for ordering of types well enough.

~~~
pcwalton
In Go, if T implements interface I, T is not a subtype of the interface type
I. T can be _converted_ to the interface type I, but it's not a subtype.

~~~
sgeop
What's the difference though? Is this true of interfaces in Java for instance,
or does it have to do with the specific implementation of go?

------
nteon
"I still wonder why we can omit commas on import/var/const blocks and just
can’t on lists and maps. Anyway, Rob Pike knows better than me! Viva la
Readability!"

import/var/const blocks rely on semicolon insertion rules, list and map
literals have a list of Elements separated by ',' [0]. I guess on the surface
level I see how this is sort of inconsistent. It would be interesting to think
about applying semicolon insertion to comma insertion.

0 -
[https://golang.org/ref/spec#Composite_literals](https://golang.org/ref/spec#Composite_literals)

------
TeeWEE
I worked on a project with go, and initially i liked it. Because the new way
of thinking, and the fast compiler. But both the error checking, missing of
generics, and missing of real functional programming paradigmas, required me
to write something very simple in a complex way.

I concluded that a simple webapp, is better written in python, and go was not
the way togo for my project. In python you can quickly generate json from
objects (yeah you can in go but only with ugly string comments). All in all,
go has its place, but when you start a new startup, watch out with go
initially.

------
oconnor663
I would add "non-pointer method receivers allow you to modify the receiver
object, but silently drop those modifications when the method exits (because
they happen on a copy)".

This is similar to the variable shadowing example in the article, in the
behavior is the same in C and so kind of makes sense for that reason. However
in both cases, Go's syntax makes it very difficult to spot the error (already-
declared variables allowed to the left of :=, method calls implicitly taking a
pointer to the receiver), where in C it would be more obvious.

------
strictfp
I've been bitten by #5 quite bad. Ranged over N elements in my slice, took the
addresses of the values, copied to new slice. Ended up with a slice with N
identical values. !?!?!? Took me about 30 mins of staring, printfing and
whatnot before I understood what was going on (the loop variable containing
the copies is mutable so you end up with pointers to it throughout the whole
new slice. And at the end the value of it is the last element in the range. So
I saw N*the last element when printing the result).

------
rtz12
Yes, Go sucks. But currently, at least for me, I think it sucks a lot less
than alternatives. No language is perfect, neither is Go.

The most annoying thing is compiler instructions with special formatted
comments. And Rob Pike calls that "elegant design".

------
thorn
I think author of this article is strangely biased towards dynamic languages.
Go is not about shortest programs in the worlds, yes sometimes code is longer
than in python. But in Go I can manage code execution and predict memory
easier better than in Python or other dynamic languages. Many things in Go
were done on purpose. Learn to use Go and it's awesome tools, like gofmt,
goimports and others.

~~~
fixermark
I love Python, up until I remember that I can't make any guarantees of program
correctness until I have 100% coverage tests on _every line of code_ because
the language is so flexible that it can't tell if a random identifier refers
to a variable name that might exist at runtime (but is not determinable to
exist at compile time), and therefore most of my variable-name typos that
would be compile-time errors in another language are runtime errors in Python.

So great for prototyping, not so great for large projects and maintenance (as
I've just put the floor of my unit test cost around a factor-of-2 more code).

~~~
TeeWEE
Indeed, with python i can program fastest, but whenever something gets big you
had wished i programmed it in golang. However, its still a valid choice to
choose python initially. It depends

------
ericfrederich
All these languages, Go, C++11/14, trying to be as concise as Python. Just
look at those slice examples. At least C++ is playing catch-up. With Go there
is no reason it had to be worse than Python right out the gate.

[https://gist.github.com/ericfrederich/c8d8513b9790106d87b7](https://gist.github.com/ericfrederich/c8d8513b9790106d87b7)

------
qihqi
Go is inspired by the C++ subset that Google choose to use (Just look for the
Google's C++ style guide to look for things that Google banned). So in many
ways, it's chosen to work as C++ in lots of corner cases.

In fact, that enabled automatic tool to convert Go compiler written in
Google's C++ to Go.

~~~
aikah
> In fact, that enabled automatic tool to convert Go compiler written in
> Google's C++ to Go.

Hmm, I thought go was written in C at first place and not C++. It seems to me
that Go creators were never big fan of C++ so I don't think it takes any
inspiration from C++ .

All I see in some kind of C + garbage collection + interfaces and some
concurrency percs. I fail to see how it was influenced by C++ in any ways.

~~~
mbrubeck
That's correct, the Go toolchain was originally written in C, and translated
from C to Go:

[https://golang.org/doc/go1.5#c](https://golang.org/doc/go1.5#c)

And of course Go's designers include some of the designers of C (well, its
predecessor B) and Limbo, and Go seems influenced more by that tradition than
by C++.

------
Artemis2
I think the author is a victim of the fallacy that Go _looks_ simple, even
though it's a very low-level language (think C without the quirks). Most of
the — very valid — points they make are a consequence of Go not hiding
complexity from the programer.

------
Kiro
I don't understand 3. How else is it supposed to work?

------
JustSomeNobody
I wish the author would have taken a little more time to polish this and be a
little more respectful.

------
pbnjay
While Go could probably be better at not letting you shoot yourself in the
foot, 1-4 seem to be code smells - you should fix your code and not the
language. 5-6 seem to be personal preference, I have no problem with either as
they are and they certainly don't trip me up. #7 as the author says himself:

> noone actually cares, it’s just fine

------
elcct
That's just part of the deal. Sometimes you just have to write few more lines
of code. Your fingers won't die from it.

------
mikestew
"Alright, the title is quite bold, I admit it. I’ll tell you more: I love bold
titles, they are all about attention."

In other words, click-bait. Oh, you think I use the term lightly? For an
article that boils down to "things about Go that aren't particularly _wrong_ ,
but I don't like", the author concludes with "I hate the language: it’s
absolute crap". Really? Because when you throw the kitchen sink into your
imports "just in case", it won't compile? (I pick on this particular example
because dragging along imports you're not even using just strikes me as
sloppy, hence coloring my view of the author.)

It's one thing to state, "I would have done this differently for these
reasons", but to call the whole bundle "absolute crap" just reeks of some n00b
who learned a single dynamic language, switched to Go, and had a hard time
figuring out why his crap code wouldn't compile.

~~~
aikah
Point 4 makes sense though , it would really help with polymorphism in Go
,without generics. This is the kind of subtle behavior that is upsetting at
times and I really think this is where the language could improve, definitely.

~~~
bobbyrullo
For every "quirk" mentioned in this article there are very good reasons for
it, which the author lacks the imagination or patience to try and reason
through. Point 4 is perhaps the best example.

So given an interface Foo and a struct FooImpl which implements Foo, why can't
we pass a slice of []FooImpls to []Foo? It's because the creators of Go are
lazy and arrogant and incompetent and don't care right?

No. Consider the situation where a []FooImpl is passed to a function F(f
[]Foo). This function decides to change one of the elements of the slice to a
different implementation, say FooImpl2, eg. f[0] = FooImpl2{}. Now the
original slice of []FooImpl's has a FooImpl2 in it. Oops, we broke type
safety. Now consider what it would take to make this work - you'd have to
somehow guarantee that functions which take []Foo don't mutate the slice. Is
that possible? Is it possible to do quickly, and still have a language that
compiles very quickly? Or we could introduce "const" and all those things from
C++ but that's a whole new level of complexity to the language. And what about
the performance penalties? A struct is a different size than an interface, so
what code is emitted during compilation, something that can handle iterating
over []your_interface and []your_struct?

So next time you think "Gosh, this bit of Go really sucks" take a moment and
think about why it was designed that way. Because the fact is, it was almost
definitely designed that way, as opposed to just overlooked or neglected. You
may not agree with the choice that was made, but with the people who work on
Go, I can guarantee that there was a conscious choice that was agonized over
and discussed endlessly, just not with you in the room.

~~~
yokohummer7
Sorry to bring up this yet-another-generics-ranty-thing, but actually point 4
is a typical issue that can be nicely solved with generics, by defining a
function that works on every type that implements Foo. In this way you can
directly pass a slice of Foo to the function and achieve type safety at the
same time. As stated by the author, there's a demand for manually constructing
an interface-slice in Go, and this shows a good example why generics can be
useful.

~~~
bobbyrullo
That's a different criticism. That's the "Go Needs Generics" issue.

I don't disagree with it, but I also agree that there hasn't been any good
solutions proposed for generics that meet the requirements that are at the
core of Go: namely, performance of the compiled program, performance of the
compiler, and performance of the developer.

~~~
yokohummer7
The reason why I think generics are relevant to point 4 is that generics can
be thought as "first-class interfaces" which seem to be wanted by the author.
Yes, the author suggests a method that is not acceptable to my taste
(implicitly converting []struct to []interface), but if Go had generics he
might have not complained about the lack of "first-class interfaces", because
generics are in some ways "interfaces on steroids".

As for the core features of Go you mentioned, sorry again for my cynical
wording, but I think they are a bit dishonest.

They stress on the performance of the program, yet being slower than C/C++ due
to the usage of GC and dynamic dispatch all the time. It was even regressed in
Go 1.5[1], because the new GC prefers latency to performance. So, they traded
performance for something considered more important.

How about the performance of the compiler? Well, the speed of the Go 1.5
compiler is ~10% worse than the previous one, because they rewrote the
compiler in Go (it was previously in C, for those who didn't know yet). Why
did they do so? Because it has advantages: reduces the barrier to contribute
to the compiler, improves the code quality, etc.. Yet they traded performance
for something they consider to be important.

And the performance of the developer... While Go is not very terrible at
developer experiences, it isn't very good either. Embracing simplicity led to
lack of expressiveness, a typical example being generics. While this isn't
entirely a bad thing, it is, again, a trade-off.

So they make trade-offs all the time. Then why are generics not considered to
be good enough to make a trade-off? Because they think so. It is their
opinion, sure, but claiming generics are impossible because performance isn't
very convincing to me.

[1]
[http://yokohummer7.github.io/blog/2015/09/01/go-1.5-regressi...](http://yokohummer7.github.io/blog/2015/09/01/go-1.5-regression.html)

~~~
bobbyrullo
Sure, there's lots of trade-offs - you can't build anything significant
without trade-offs. Also, you can still say performance is a value and trade
it away for other things, eg GC. It's a bit silly to say that if something
isn't as fast as C++/C right away then it doesn't take performance seriously.
I don't think anyone's being dishonest in making such trade-offs - if you have
multiple competing values then you need them.

The big difference with stuff like GC and re-writing stuff in go slowing the
compiler time is that they are not inherent to the language. That stuff can
and will improve. With generics if done incorrectly, it's more or less
permanent. So I appreciate the conservatism there, and don't think it's fair
(or accurate) to say that it's dishonest.

~~~
yokohummer7
> The big difference with stuff like GC and re-writing stuff in go slowing the
> compiler time is that they are not inherent to the language.

Actually, I think GC is inherent to the language, and that's why I listed it
as one of the trade-offs that _Go_ made (not the Go implementation made).
Almost every language construct depends on GC, e.g. append(), make(), and
more. Even the following innocent-looking code:

    
    
      func f() *int {
        a := 1
        return &a
      }
    

is GC-dependent, because it would result in a dangling pointer in non-GC
languages. But the code is perfectly fine in Go because GC is inherent to the
language. It is not possible to make GC optional in Go, so the performance
penalty will stay there forever, only alleviated as the implementation matures
(or sometimes regressed, as Go 1.5 shows), unless you use only unsafe.Pointer
all the time.

------
dang
We replaced the baity title with something more neutral, in keeping with the
HN guidelines:

[https://news.ycombinator.com/newsguidelines.html](https://news.ycombinator.com/newsguidelines.html)

~~~
kzhahou
Dang, I think you're too aggressive with article renames. The author claims
that Go is poorly designed. And that's the title of the article. Yes, it's a
provocative opinion (and the article text is loud), but the title itself was
not outrageous hyperbole. I disagree with other commenters here: just because
a controversial opinion will (naturally) gather more clicks, doesn't mean it's
linkbait.

The articles here on HN also surface on reddit and other forums. I frequently
click links on HN just to discover I'd read them already.

The title often contains a clue as to what I'll find in the article. The
author presumably gave it some thought. When HN editorializes titles, I lose
that context before I decide to click.

~~~
dang
You may not think this was linkbait, but I guarantee you that if this article
were on HN's front page with that title, the thread would become about the
title. All you need to do is look at the comments that were posted before we
changed it.

Your objection is really to HN's title policy. In my view that policy is a
critical aspect of this site—indeed the longer I work on HN the more critical
it seems. So I have to disappoint you here; it's not going to change. Huge
numbers of HN readers would be up in arms if it did, even though no reader
agrees with every particular edit moderators do.

~~~
kzhahou
Well, it looks like my only recourse is to mount an aggressive campaign to be
the new HN moderator, take you down, restore the original titles, and
eventually get run out due to various lurid scandals involving clickbots.

Thanks anyway for the reply :-)

------
px1999
I guess I'm a "a pussy, 9-year old boy or afraid of little bit “strong”
writing.", because as soon as I saw that sentence I lost all interest in
finishing the post (though it was pretty linkbaitey in the bit I did read so I
had marginal interest in the first place).

Shit like that is why we have gender problems in the industry.

------
soroso
FUD

------
smegel
> it’s not foreach from C++.

Ah the penny drops. We have a whiny C++ programmer on our hands.

