
Why I Don't Like Golang - dlcmh
http://www.teamten.com/lawrence/writings/why-i-dont-like-go.html
======
ianleeclark
AFter writing a few non-trivial projects (only thousands-ten-of thousands of
lines), I'm starting to really understand every gripe about Go.

The standard library is very nice, but the language constantly feels like it's
working against me or I'm having to circumvent some intended feature (no
generics, while not a problem in the beginning, has continually worn down on
me). Besides that, reason 9 is a huge nuisance which needs to be resolved,

------
znpy
One thing I'd like to see in Go, is the possibility to ask the compiler to not
bother me for defined-but-not-used and/or imported when doing prototypes.

You know, "I just changed this little thing and I want to see what happens".

~~~
ngrilly
Have you tried goimports? It helps a lot with this.

~~~
hehheh
Let's say you comment out some line of code in go and go complains about an
unused import. You run goimports and it removes the import. If you uncomment
out that line of code and re-run goimports, will goimports automatically re-
add the _correct_ import statement every time?

~~~
ngrilly
> Let's say you comment out some line of code in go and go complains about an
> unused import.

If you setup your text editor to execute goimports on save, it won't happen,
because the import will already be removed.

> If you uncomment out that line of code and re-run goimports, will goimports
> automatically re-add the correct import statement every time?

Most of the time, yes, but not every time. It works well for the standard
library and when the last segment of the package name is enough to identify
the package.

------
speps
The Go authors and contributors probably know a lot of those issues and how
the community feels in general. However, they made a strong point not to
change v1 to accomodate for changes like generics. We'll see what happens with
v2... one day.

------
ngrilly
1\. Unlike the author, I think using capitalization for exported identifiers
is great. It's hard to believe that having to name unexported constants
"entirely in lower case" can be a "recurring source of discomfort".

2\. This is called "structural typing" and it's one of Go's greatest features.
It looks like the author prefers "nominal typing". Both approaches have their
pros and cons. See
[https://golang.org/doc/faq#implements_interface](https://golang.org/doc/faq#implements_interface).

3\. Go by design doesn't have exceptions. See
[https://golang.org/doc/faq#exceptions](https://golang.org/doc/faq#exceptions).
github.com/kisielk/errcheck can be used to make sure errors are checked
everywhere (but I agree this is not ideal).

4\. I don't get that part. Sounds like nitpicking to me.

5\. I don't get it either. If there is a "collision", you can use an alias.
And I personally don't like having to repeat fully qualified package names
everywhere. On this topic, I prefer Go's approach to Java.

6\. Go has been designed to automatically generate code! A lot of tools do
that all the time, the best example being gofmt. The compiler being strict is
more an advantage than a liability for this purpose. But I agree with author
about the issues created by packages sharing the same default name. Would be
curious to know the advice of the Go team on this.

7\. I mostly agree about missing the ternary operator, sometimes. But I don't
miss the code I read in other languages that abuse it. I'm 50/50 on that.

8\. I agree about sorting being "clumsy". This is being worked on at
[https://github.com/golang/go/issues/16721](https://github.com/golang/go/issues/16721).

9\. I agree about Go not providing anything builtin or well-known for
dependency versioning, but I completely disagree about vendoring. See
[https://golang.org/cmd/go/#hdr-
Vendor_Directories](https://golang.org/cmd/go/#hdr-Vendor_Directories).

10\. Missing generics is probably the most talked topic about Go. I miss them
sometimes. I keep hoping Go solves this one day. Here is Russ Cox explaining
why Go doesn't have generics today:
[https://news.ycombinator.com/item?id=9622417](https://news.ycombinator.com/item?id=9622417).

~~~
junke
I don't get how "great" it is to let capitalization be used for exported
identifiers. What is the rationale behind this?

~~~
ngrilly
According to Rob Pike:

 _" This was not an easy design decision. We spent over a year struggling to
define the notation to specify an identifier's visibility. Once we settled on
using the case of the name, we soon realized it had become one of the most
important properties about the language. The name is, after all, what clients
of the package use; putting the visibility in the name rather than its type
means that it's always clear when looking at an identifier whether it is part
of the public API. After using Go for a while, it feels burdensome when going
back to other languages that require looking up the declaration to discover
this information."_

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

Must be noted that any identifier that doesn't start with an uppercase letter
is not exported. This makes possible to use an underscore to mark unexported
identifier and still use uppercase letters (like _Name or _SOME_CONSTANT),
which is a common practice in many programming languages (like Python). This
is not idiomatic in Go, but it's possible.

~~~
ngrilly
Why the downvote?

~~~
junke
I didn't downvote either. I would have like to read a more convincing answer,
but this always come down to "Rob Pike says so". I found an old thread about
this btw:
[https://news.ycombinator.com/item?id=5201461](https://news.ycombinator.com/item?id=5201461).

~~~
ngrilly
It's not because "Rob Pike says so". It just happens that I agree with him on
this matter, which is why I mentioned his answer :-) Thanks for the link,
including tptacek comments, which are very convincing.

~~~
junke
> As a result, a lot of packages do The Simplest Thing That Could Possibly
> Work and just expose simple functions. The result is usually refreshingly
> clear.

That's what I do too, but I don't change names. I use "export" declarations
for packages, which are completely orthogonal to what the symbol represents.
Less naming problems. The capitalization thing would be in the "Meh" category
for me, that's all.

~~~
ngrilly
Interesting! In which language?

~~~
junke
Common Lisp (packages and symbols are first class). There are some gotchas at
first but then they feel quite natural. You write your code in one place and
manage visibility elsewhere.

This allows for example to make a symbol exported in different packages, or
take separate code and provide a unified facade package. But most of the time
you just need to define the public interface of your code and this is quite
easy.

------
regecks
> but its import system is actively hostile to vendoring

? It literally has built-in support for a vendor directory.

Great cover image though, I lol'd.

------
velodrome
I wish the author mentioned a better Golang alternative. Rust?

~~~
lossolo
I am switching from Go to .NET Core (C#) at the moment for one application.
Great experience, better language features, better syntax, easier and nicer to
build huge projects with a lot of people. I still like Go but C# is light
years ahead with features and i think Go is better for small, performant apps
like couple KLOC but when you have big team, you need expressiveness of the
language, generics and good composition then C# is better in my opinion.

~~~
ngrilly
I don't understand the rationale underlying the link you make between having a
big team and needing expressiveness/generics. Go has been explicitly designed
for big projects with big teams, and the authors have explicitly limited
language features to make big projects with big teams more maintainable.

That said, coming from Python, I sometimes miss its expressiveness. But when I
switch back to Python, I miss Go "straightforwardness".

------
pawadu
#2 maybe, #7 for sure...

But the rest are either (A) it doesn't work the way I want it to work or (B) I
haven't read the manual and it's your fault.

~~~
coldtea
Aside from 2 and 7, also 8, 4, 3, 10, 11 are all awful, and they can't be
written down as "personal preference" or "RTFM".

It's 2016, Generics are not some controversial "personal preference" and
neither are badly designed APIs.

~~~
pawadu
Are generics really a requirement for a 2016 programming language? Take a look
at the TIOBE index, how many of the top 50 languages have _proper_ generics
support?

[http://www.tiobe.com/tiobe-index/](http://www.tiobe.com/tiobe-index/)

edit: not saying generics are bad, but not having generics in golang was a
design decision not an oversight.

~~~
coldtea
> _Are generics really a requirement for a 2016 programming language? Take a
> look at the TIOBE index, how many of the top 50 languages have _proper_
> generics support?_

How many of them are 2016 programming languages, solving 2016 problems -- as
opposed to 2 and 3 and 5 decades old languages designed in another era?

(Not to mention that even some 3+ decades old languages have generics...)

> _edit: not saying generics are bad, but not having generics in golang was a
> design decision not an oversight._

I think in some languages design decisions and oversights are not
contradictory.

~~~
pawadu
I guess the point I wanted to make was that having proper generics in a
language is very hard and whats why very few languages attempt to implement
it. And people are still arguing whether generics in C++ do more harm than
good (i.e. complicate debugging).

So not supporting generics is a design decision and not always a bad one.

~~~
coldtea
> _I guess the point I wanted to make was that having proper generics in a
> language is very hard and whats why very few languages attempt to implement
> it._

I'm not sure about this, I believe it's a solved problem.

Languages have had them for decades, and lots of different avenues have been
explored. Neither Java nor C# (and those are mainstream pragmatic languages,
not experimental academic affairs) have particular issues with their
(different) respective Generics implementations (except the obvious tradeoffs
I mean -- but it's not like programmers or their compiler writers are
strugging because of them in any way).

They are also quite easy to add to a language (even hobbyist languages have
them) -- I'm not sure why you say that "very few languages attempt to
implement it".

The big two used by tens of millions (Java and C#) have them, C++ has them, F#
has them, Swift has them, Scala has them, Delphi had them, lesser used
languages like Ada, Julia, Haskell, D etc have them. Heck, almost all modern
mainstream languages have them.

"Proper generics" is a red herring put forth by Pike, where its would only be
OK to have generics if it came without any tradeoff at all, where tradeoffs
even include the compiler being harder to write.

Yeah, I don't think they can magically created pain free either. I do think
they solve a lot of pain where it matters: for the programmers.

> _And people are still arguing whether generics in C++ do more harm than good
> (i.e. complicate debugging)._

That's because generics in C++ come with all the template baggage and a full
turing-complete and complicated scheme to work with them. There's no need to
go there.

~~~
codygman
> "Proper generics" is a red herring put forth by Pike, where its would only
> be OK to have generics if it came without any tradeoff at all, where
> tradeoffs even include the compiler being harder to write.

This. To further add to this, an argument against generics used to be worries
about showing compile times, but that didn't stop rewriting the compiler in Go
or implementing SSA. Go's compile times are still much slower than they were.

Point being that generics aren't seen as important, not as being too difficult
to implement correctly.

~~~
remus
> ... but that didn't stop rewriting the compiler in Go or implementing SSA.
> Go's compile times are still much slower than they were.

I think the trade offs in those cases were pretty clear. The switch from c to
go was made so that compiler development would be easier, and indeed you could
well argue that it was a big enabler in work like reducing GC pause times.
Similarly, one of the big reasons for switching to the SSA back end was to
enable improved optimisations down the line. I think the results of this work
are fairly clear already: in 1.7 binaries are generally smaller than 1.6,
sometimes by as much as 20-30%.

I think the trade-offs for generics are less clear. Compile times may
increase, they'd add complexity to any implementation and, perhaps most
importantly, they'd add significant complexity to the language. On the other
hand, they make certain classes of problem substantially easier and
significantly simplify some APIs.

------
lazyant
# 4 "This is all part of the “convention over configuration” movement. It’s
fine for small projects but bites you on large ones, and Go was meant to
address the problem of “programming in the large”."

Isn't that the opposite? conventions (even ugly ones, or annoying ones) help
with consistency across many developers or large projects.

------
fithisux
The only problem that makes me angry with Golang is that a pointer to a struct
and a struct member can both be referenced with the dot '.'. For me it makes
the code unacceptably non readable.

