
Why I Don't Like Golang (2016) - Danieru
https://www.teamten.com/lawrence/writings/why-i-dont-like-go.html
======
gerbilly
Does anyone remember reading K&R for the first time?

To me seemed like C was such a tight, perfect little design.

Only thirty keywords, and simple consistent semantics.¹

When I first learned it, it was still pre ANSI, and you declared a function
like this

int f(a)

char *a

{

}

The ANSI style function declaration was maybe the only innovation that came
after that that significantly improved the language.

I remember in the late '80s knowing my compiler so well that I could tell you
what the stack frame would look like pretty much anywhere in my code. It was
awesome to have that level of familiarity.

Soon after that things started to get more complicated, and I did a lot of
Java, and I never again felt as dialed in to those languages as the late 80s C
that I started out with.

The K&R book is worth a read if anyone missed it. It's beautifully written. A
far cry from the 'opinionated' copy that you often find on the Go website.

Personally, I don't think you can make similar claims about Go's design or the
'because I told you so' tone that surrounds it.

1: Yes, I know, undefined behaviour, but this is my post and this is how I
feel about C.

~~~
lmm
Can't say I got that feeling at all.

Smalltalk is a tight design. So is Lisp. So is Forth. So is APL. C's design
just feels like a pile of... stuff. Arrays are almost but not quite the same
as pointers. You can pass functions but not return them. There's a random
grab-bag of control flow keywords, too many operators with their own
precedence rules, and too many keywords given over to a smorgasbord of
different integer types with arbitrary rules for which expressions magically
upconvert to other ones.

~~~
fao_
FYI: 2am possible rambling on design and software

Funny, I got the same feeling from Smalltalk and Lisp.

I own both "Common Lisp: The Language" and "Smalltalk-80: The Language and its
Implementation", and while there are many ways those languages could be
described as 'tight' (tightly-coupled, perhaps), at no point can you look at
the C language and say "This could be smaller" without significantly removing
functionality. Ok, perhaps there are some things around array/pointer syntax,
etc. but the room for removing things from the language is very small.

LISP and Smalltalk are both 'kitchen-sink' languages. As I understand it (i.e.
Unless I misread something or skipped a page) for an implementation to be a
proper spec-conforming instance of Smalltalk-80, a screen and graphics server
is required. Indeed, Smalltalk-80 requires a very specific model of graphics
display that is no longer appropriate for the time. Steele's Lisp, has a
number of functions that one could strip out and nobody would care or notice
very much.

On the other hand, all of the C that is there serves a purpose.

Perhaps the only thing in your list that does feel like a tight design in
addition to C, is FORTH. But FORTH puts the burden for the programmer to
remember what is on the stack at any given time. It has some beauty, indeed,
but all of the abstractions seem inherently leaky. I haven't programmed in
FORTH, however, so I can't really talk more about how that plays out in
practice.

If the "There is nothing else to remove" does not resonate with you, then I
think the perspective of the OP, and myself, and others, when we call C a
"small"/"tight" language, is that essentially, C was born out of necessity to
implement a system. Conversely, the 'batteries included' aspect of Smalltalk
and Lisp more or less presume the existence of an operating system to run. It
feels like the designers often did not know where to stop adding things.

Most of the library functions in C, can be implemented very trivially in raw
C. Indeed, much of K&R is just reinventing the library 'from scratch', there
is no need to pull out assembly, or any more assumptions about the machine
other than "The C language exists". Whereas, a lot of the libraries of
Smalltalk and Lisp seem bound to the machine. Not to harp on too much about
the graphics subsystem of smalltalk, but you couldn't really talk about
implementing it without knowing the specifics of the machine. And while much
of Lisp originally could be implemented in itself, Common Lisp kind of turned
that into a bit of a joke. Half the time when using it, it is easier and
faster to reimplement something than find whether it exists.

Apologies if this is repetitive or does not make much sense.

~~~
nickloewen
I agree with you, but perhaps you are reading “tight” slightly differently
than the way the original poster intended it?

To me, ANSI C is “tight” in the sense that it is made up of a small set of
features, which can be used together to get a lot done. But the design of the
features, as they relate to each other, can feel somewhat inelegant. Those
different features aren’t unified by a Simple Big Idea in the way that they
are in Lisp or Smalltalk.

Lisp and Smalltalk, then, have “tight” designs (everything is an
s-expression/everything is an object) which result in minimal, consistent
semantics. But they also have kitchen sink standard libraries that can be
challenging to learn.

(Although to be fair, Smalltalk (and maybe Common Lisp to a lesser extent) was
envisioned as effectively your whole OS, and arguably it is a “tighter” OS +
dev environment than Unix + C...)

FWIW, I am learning Scheme because it seems to be “tight” in both senses.

------
losingthefight
I have been using Go in production since 2015 and can honestly say that other
than the ternary operator, none of these have been a major issue for me.
Granted, I am doing mostly REST API development so my use cases may be
different, but I have never had an issue with capitalization or which
interfaces are implemented. The tooling is by far some of the best I have used
in a language. Paired with a good editor (I personally use VS Code on Ubuntu
18.04 as my main setup) and I have yet to miss exceptions or wonder what my
code is capable of doing.

That being said, Go isn't perfect by any stretch. Sometimes panic ins Go
routines can be very hard to trace. The transition to Go modules is
challenging for larger projects with versions beyond 1.x (when I started it
was Glide, then dep, now go mod, which has been a bit frustrating). However, I
wouldn't go back to Java, C#, PHP, or NodeJS if I had the choice.

My go to in the server space is Go and Elixir. I don't feel a desire or need
for anything else, but again, that's me. You know your use case better than a
stranger on the internet :)

~~~
sdegutis
If you're just writing a REST API, I wonder, why did you choose Go for this
instead of Java or Python?

~~~
mi100hael
I also prefer writing REST APIs in Go.

\- Compared to Java: Ecosystem is way over-engineered. You might get along
just fine without writing a bunch of boilerplate and factories and XML
configs, but sooner or later you're probably going to pull in some dependency
that does and have to deal with a bunch of clunky APIs and other annoyances.

\- Python: Possibly the only language that's even worse at dependency
management than Go. Installs packages globally. The solution is to create a
"virtual environment" which is code for hacking up your PATH.

\- Node: I dislike the quirks of Javascript like remembering the difference
between == and ===, undefined vs null, etc. I haven't used Typescript which
may solve some of those language issues. I also dislike dealing with
promises/callbacks for so many operations.

I like Go because:

\- I can compile to a single statically-linked binary and cross-compile for
other platforms

\- I can choose to either vendor dependencies or use go-dep to create a
dependency lockfile. I can have multiple GOPATHs with minimal magic.

\- The "go" CLI handles pretty much everything I need without an explicit
config file like pom.xml or package.json.

\- The language lacks features. There is no magic. Way more so than even
Python, there is one obvious way to do things and there's even an official
style guide, so it's easy to jump into someone else's code and understand
exactly what's going on immediately. After working with Scala professionally
for a few years, I firmly believe this to be a feature, not a flaw.

\- The standard library is incredibly comprehensive. It's completely possible
to write a web service without importing a single external dependency. There
has been a lot of thought put into library APIs for things like byte
Readers/Writers and HTTP handlers, to the point that external libraries still
usually stick to these standard interfaces. Contrast that with a language like
Python where urllib sucks so everyone uses requests.

~~~
jayd16
I see this complaint against Java a lot. If you're going to slum it in a
language with no ecosystem so you don't feel overwhelmed, why not just use
less of the Java ecosystem?

~~~
apta
These complaints are usually by people who have not been using modern Java, or
who have just been reading or hearing unsubstantiated claims about it. Or who
haven't worked in large golang projects to see all the mess it brings with it
because of how underpowered it is.

Look up libraries like Spark[1] or Javalin[2] and you get something quite
light weight. Or DropWizard[3] if you need something more holistic.

That being said, the moment you need something more involved, say validation,
DB access, pre- or post- endpoint call processing (e.g. for authorization),
then golang completely falls on its face. There is nothing in golang that
compares to Jooq[4] for instance, and because golang doesn't have annotations,
you can't do automatic validation or authorization, and you end up having to
do everything manually in a verbose and error prone manner.

For static compilation in Java, GraalVM is supposed to be quite good[5]

[1] [http://sparkjava.com/](http://sparkjava.com/) [2]
[https://javalin.io/](https://javalin.io/) [3]
[https://www.dropwizard.io/1.3.12/docs/](https://www.dropwizard.io/1.3.12/docs/)
[4] [https://www.jooq.org/](https://www.jooq.org/) [5]
[https://quarkus.io/](https://quarkus.io/)

~~~
fileeditview
You are right that big (especially enterprise) projects in Go are also a mess.
But one of the main reasons is that people have a Java (or C++) background and
try to replicate all sorts of complexity.. not because Go is "underpowered".

Also if you compare those codebases to Java (again enterprise) projects of a
similar size they seem quite readable instantly..

~~~
apta
> You are right that big (especially enterprise) projects in Go are also a
> mess. But one of the main reasons is that people have a Java (or C++)
> background and try to replicate all sorts of complexity.. not because Go is
> "underpowered".

That hasn't been my experience at an employer. Their devs mainly had Python
and NodeJs experience and similar languages (which is what the first version
of the code base was written in), and disliked "enterprisey" code. Somehow,
the decision to move to golang was made.

Yet, they somehow managed to come up with their own mess, and yes it is mainly
because how underpowered golang is. I keep thinking about how much simpler the
code base would be if it were written in Java, let alone something like
Kotlin.

------
wwweston
If there's anything I'd draw the most attention to from this, it'd be the
conclusion:

"If your program is small and can mostly be described by what it _does_...
then Go is fine. If it’s large, if it has non-trivial data structures... or if
it will be dealing with a lot of data from the outside, then the type system
will fight you for no benefit and you’re better off using a different static
language (where the type system helps) or a dynamic language (where it doesn’t
get in your way)."

That's a much better way to express my sense after almost a year of working
with it that I'd ended up with a Pascal-like subset of Java with most of the
liabilities of the former. And I wanted to like it going in ("hey, some people
love it, and it's more or less Gosling's statement about Java w/o classes come
to life!").

------
kstenerud
This article is from 2016, but it's still relevant. Even in medium sized
projects I've been bitten by many of these issues, and for a language that's
supposed to eschew magic, there's an awful lot of wizardry going on.

Stopping compilation with an error for every unused import & variable is
particularly annoying, so much so that I've patched the go compiler to treat
them as warnings instead [1].

Ultimately, I think the problem boils down to a language that outgrew its
original design, and hasn't evolved elegantly (yet).

[1] [https://github.com/kstenerud/go](https://github.com/kstenerud/go)

~~~
cr0sh
> Stopping compilation with an error for every unused import & variable is
> particularly annoying

It's been a long while since I last touched Golang, but I recall the process
of learning it.

My coworker and I were tasked with creating an interface for our employer (a
cloud service provider) to allow Rancher (or clients of Rancher - I forget) to
use our backend system (which was built out of a combination of PHP, Java, and
Bash - among other parts) to provision servers.

Neither my coworker or I had ever touched Go; we were PHP developers. But
Rancher used it, had examples, and we set out to learn it (while we were
employed as PHP developers, we both had extensive prior experience with a
number of other languages).

It took about a week until we were comfortable enough to begin our
implementation, and about a month later we had a working library written in Go
that we understood and had documented well, with tests.

But the process: Exactly like you noted! We railed, we gritted our teeth! We
shook our fists at heaven and loudly proclaimed "WHY?!"

Because we were so used to leaving things lying about in PHP; for
experimentation, debugging, and other reasons. But Go wouldn't let us - no-
siree-bob! - you had to make it just so before it would successfully compile,
and we tore our hair out over it. Day after day, week after week...and then:

Something changed. We understood. We realized why the designers of Go did what
they did, and we also started to wish fervently that PHP could be the same
way. We also noticed that by these changes, we no longer needed to leave this
"cruft" around, this "dead code" that could possibly cause us to trip up, or
wonder if it was needed later, or whatever. Yes, it made development more
difficult - but we came to recognise that it helped greatly to prevent errors,
or future problems, and kept things very maintainable.

But like I said - I haven't used Go in years since that time; there hasn't
been a call or need for it, but it is a language that I keep in my "back
pocket" just in case I ever need it. Maybe things have changed a lot since
then, or maybe they haven't. Regardless, I learned from that experience that
sometimes you have to power and struggle through things before the revelation
appears. I got to experience a fairly unique language, and I feel that I'm
better as a developer for it.

~~~
jeremyjh
This is a solved problem in every compiled language I've ever used - at least
10 of them. Unused variables is a warning, and your CI build compiles with a
-werror / \--warnings-as-error flag. Thats it. All the benefits you mention,
without the "slowing down development" that you mention.

~~~
dx034
But people ignore warnings. The only way to keep code clean of unused
variables and libraries (and prevent potential bugs where typos led to unused
variables) is to disallow it completely.

In the end it's just about the variables anyway, most IDEs will remove unused
libraries automatically.

~~~
jeremyjh
Did you read my comment? How do you ignore the fact that your PR build is
failing?

------
abvdasker
> Capitalization also restricts visiblity to two levels (package and
> completely public). I frequently want file-private identifiers for functions
> and constants, but there isn’t even a nice way for Go to introduce such a
> thing now.

To me this is more of an issue with not understanding some of the conventions
the language pushes you towards. An example of this common stylistic mistake
is when some repos will have a `lib` package with a large number of utility
functions spread across different files. It runs into the author's issue of
function and constant collisions. The solution is to group together utility
functions into many small packages, which has the added benefit of changing
the code at the call site from something like this:

    
    
      lib.NewUUID()
    

To something terse like this:

    
    
      uuid.New()
    

I've found that Go has lots of these sorts of nudges — dependency cycles
generating a compiler error, for example — where the language enforces good
style and organization.

However, if the Go compiler is going to enforce these rules, maybe it could be
more helpful by suggesting the design tweaks that would help to avoid them,
rather than forcing developers new to Golang to go through a kind of trial and
error process.

------
_bxg1
Unrelated thoughts:

> Structs do not explicitly declare which interfaces they implement. This is
> done implicitly by matching the method signatures. This design makes a
> fundamental error: It assumes that if two methods have the same signature,
> then they have the same contract.

Isn't this just duck typing? Don't other languages renowned for their type
systems do this?

> There’s no ternary (?:) operator. Every C-like language has had this, and I
> miss it every day that I program in Go. The language is removing functional
> idioms right when everyone is agreeing that these are useful.

Expressive if/else is much more readable. Of course if Go doesn't have that,
removing the ternary operator is a bad call.

> The tried and true approach of providing a compare method works great and
> has none of these drawbacks.

Hmm... except in anonymous cases. This author clearly has some Java stockholm
syndrome.

> The append() function modifies the array in-place when it can, and only
> returns a different array if it has no place left.

That's horrifying.

~~~
weberc2
> Isn't this just duck typing? Don't other languages renowned for their type
> systems do this?

It's "structural subtyping", which is the type-safe equivalent of duck typing.
It's a feature that allows implementations to exist without needing to know
exactly every interface they implement. TFA's concern is purely theoretical.

> That's horrifying.

append() doesn't operate on arrays, it operates on slices. Arrays are fixed-
length, contiguous blocks of memory that can't be appended to. Slices are
backed by arrays, and if you append to a slice whose backing array is full, it
will "grow" by allocating a bigger array elsewhere and copying the original
data into it. This is a pretty standard data structure in most languages.

~~~
fileeditview
I love go and all but append has some serious problems in my opinion. Look at
this code for an example.

[https://play.golang.org/p/qWCnF7d7Fl9](https://play.golang.org/p/qWCnF7d7Fl9)

This is unexpected behavior at best.

~~~
masklinn
At a fundamental level, it's not so much append as slices being shareable
_and_ doubling up as vectors (being appendable). That's the core sin.

------
dawkins
I have been using Go in production since 2012 and I find it a fantastic tool.
Except for point 8 ("The sort.Interface approach is clumsy") the rest are
features for me.

I am so grateful for the Go creators for having made it as it is. What worries
me is the recent changes: modules (never had a problem with GOPATH) and Go 2
proposals. I hope they are able to keep their vision as it started.

~~~
baby
Same here, people can complain but the reality is that more and more people
find Golang a great language to use day-to-day. Honestly I think it's here to
replace Java and to stay.

Same as Rust replaced C and C++.

That anyone would want to write C/C++ or Java today is absurd, except if
they're old.

~~~
thrower123
These are still very niche languages. Go has a better shot, albeit still long,
with the weight of Google behind it, but there is an unbelievable amount of
inertia. Rust certainly hasn't replaced C/C++ to any real degree yet.

Maybe time will tell, but I'd lay money that there will be a lot of people
still working on C, C++ and Java codebases in fifty years, just like there is
a boatload of COBOL and even MUMPS software still out there in the wild today.

~~~
baby
I'm not saying that these languages have replaced their older versions, but
that one would be crazy if given the choice to choose to do Java/C/C++ for
work :)

------
bborud
I'm surprised that someone can use Go for 3 years and still be hung up on the
things that most people appear to get over in the first month.

~~~
seandougall
If you get a pebble stuck in your shoe, you can usually get over it within a
couple minutes, and start to ignore the minor annoyance. But if it stays there
all day, it could eventually get pretty painful. It all depends on how much
walking you do.

~~~
weberc2
And to the parent’s point, most people simply learn to remove the pebble in
the first month. ;)

~~~
matt_kantor
The pebble is still there, but most people learn to walk in such a way that
they don't put their full weight on that part of their foot.

This might not be the most efficient way to walk, but once you've done it for
a while it starts to feel natural.

~~~
weberc2
And then you switch to Go thereby removing the metaphorical pebble, but you
have to relearn how to walk efficiently. See how pointless this is?

~~~
matt_kantor
I guess you just don't like the metaphor?

I thought you had misinterpreted it, so I was trying to help clarify by
extending the metaphor. In case we're still misunderstanding each other: the
pebble is the language's warts, which you can't remove, only avoid or work
around. Every language has its warts, but we're talking about Go's here.

You don't have to be rude about it.

~~~
weberc2
I wasn't being rude, and I understood your point. I was pointing out that the
metaphor can as easily be used to support Go's position as the critics'
position. The metaphor lacks substance. Criticism != rude.

~~~
matt_kantor
"See how pointless this is?" sounded very snippy in my head, but perhaps I
didn't read it charitably enough.

------
betandr
I totally get all of these points and understand them, and they're really why
I _do_ like Go. Implicit interfaces, for example, means you don't need to
change code for something to implement this interface. It's a powerful thing
that I find really great, especially coming from years of Java having to
update everything I want to implement the new interface. If I don't have
access to the code, then it's more boilerplate to do that. With Go, I create
the interface I want and anything that implements it immediately works.

I understand why people might dislike a particular language and that's cool.
That's why there are many languages and we have the ability to choice what
works best for us.

------
lkramer
most of these seems reasonable, but they are not big enough for me to actively
dislike the language.

The capitalisation is maybe the most annoying for me, I think it was designed
with an IDE in mind (which would be able to automatic update all references),
but I still find it a flawed design to have to touch potentially a lot of
files, many places to change something from private to not private.

The problem with err has also bit me a few times. I don't like exceptions very
much, but a solution like he suggests where a variable can only be ignore
explicitly would solve it.

Go is not perfect, but for me there is nothing else better for microservices
that I have come across.

~~~
_bxg1
> where a variable can only be ignore explicitly

Like Rust :)

~~~
lkramer
I keep meaning to check it out :)

~~~
_bxg1
I'm still pretty new to it and I've never used Go, but Rust seems to address
most if not all of these problems, while serving many of the same original
design goals of Go. Probably its biggest disadvantage is the learning
curve/iteration speed: it doesn't make it easy to just hack things together,
especially when you're first learning.

~~~
weberc2
Yeah, iteration speed is a pretty big blocker for adoption in a lot of
domains. Go isn’t perfect, but it lets me get things done today. That said, I
appreciate that Rust exists for safety/performance critical domains, and as
Rust matures (e.g., as it’s async story solidifies and consensus emerges
around various HTTP libraries, etc), it will be more competitive for general
purpose application development. But I suspect there will always be a
significant productivity gap.

~~~
_bxg1
I suspect that once I've better-internalized the borrowing mechanisms I'll be
able to move at a reasonable clip in Rust. The build/package management
environment is pretty batteries-included and "just works", and the syntax
isn't particularly _verbose_ , just _strict_. Once getting things to compile
is no longer a debugging process for me personally, I don't really see any
other intrinsic bottlenecks.

------
diamondo25
Most of the items explained are non-issues and part of why Golang is how it is
today. Lets hope we can keep the language as-is and don't go back to old
decisions and remove features like Scala have been doing the last years...

~~~
norswap
<reference needed>

~~~
diamondo25
One of the praised functions in Scala 2.8 was postfix operators, allowing
things like:

    
    
        Seq(1, 2) map _ + 100
    

They are getting rid of it: [https://contributors.scala-lang.org/t/lets-drop-
postfix-oper...](https://contributors.scala-lang.org/t/lets-drop-postfix-
operators/1457)

Unit functions were a thing, just write:

    
    
        def A() { ... }
    

This is inalid since 2.13. You have to specify its a unit:

    
    
        def A(): Unit = { ... }
    
    

Most of the ideas in scala were to remove boilerplate, but they backfired. The
top example had an issue, were the following conversion used to be made:

    
    
        z op ()
        // would equal to
        z.op()
        // instead of (fixed in 2.13)
        z.op(())
    

Arrows are used for creating key-value pairs and such. Someone added nice
Unicode equivalents for them. Those got deprecated in 2.13

    
    
        Deprecated: ⇒, →, ←
        Use instead: =>, ->, <-
    

[https://github.com/scala/scala/releases/tag/v2.13.0](https://github.com/scala/scala/releases/tag/v2.13.0)

~~~
twic
They've also significantly simplified the collections classes, removing quite
a bit of abstraction. That was always one of the things that struck me as most
ludicrous about Scala, so i was pleasantly surprised by that.

Indeed, i've been impressed by the Scala team's recent willingness to remove
complex features generally. I didn't see that coming.

------
jrs95
Biggest issues for me here were generics & the dependency situation, both of
which are being fixed. But even back then, I loved using Go, mostly for what
it DIDN'T have. Even ternaries, while convenient, inevitably lead to someone
using them to write some really stupid shit that's hard to read.

Overall, I'm a fan of losing a few helpful abstractions in order to get rid of
all the bad ones, whether in the language itself or in it's ecosystem. And Go
delivers on that.

------
DaveInTucson
I thought one of the basic lessons we learned from the last 70 years of
programming language design is that it's a bad idea to make semantics depend
on lexical structure.

I'm really surprised people like Rob Pike and Ken Thompson would design a
language where the visibility of an identifier depends on the case of its
identifier.

~~~
sim_card_map
Interesting. Do you have links? Or maybe a short summary why this is bad?

~~~
apta
It becomes very annoying and tedious to refactor when you need to change
visibility. Suddenly, a single line change (e.g. changing private to public)
needs an IDE to refactor it and make sure it gets all instances (which is
quite ironic given that golang proponents generally shun IDEs). Now depending
on how many instances changed, you would need to split up your diff for
readability, or clutter your diff with needless changes.

~~~
zemo
> a single line change (e.g. changing private to public) needs an IDE to
> refactor it

the language comes with a rewriting tool that rewrites arbitrary expressions.

gofmt -w -r 'thing -> Thing' *.go

~~~
apta
Still more and unnecessary effort compared to changing one word.

------
dang
A thread from 2018:
[https://news.ycombinator.com/item?id=16414098](https://news.ycombinator.com/item?id=16414098)

From 2016:
[https://news.ycombinator.com/item?id=12356823](https://news.ycombinator.com/item?id=12356823)

------
ajxs
At the risk of courting controversy, I'll confess that I haven't even so much
as considered using Golang on the basis that it's a language ostensibly
controlled by Google. I have reason to believe that my moral stance against
Google is shared by many in the development community, but I don't recall ever
seeing this sentiment extended to Golang. The anti-Oracle sentiment is thick
and heavy in the development community, mainly surrounding Oracle's predatory
business practices and how they leverage them via Java. I've completely
avoided investing in Golang for that very reason, I don't want to ever become
beholden to Google's services in order to maintain further development in this
language.

------
kjgkjhfkjf
You’re not forced to use the "imperative verbosity" in the article. The
following is shorter and more idiomatic.

    
    
        serializeType := model.SerializeNonArchivedOnly
        if showArchived {
            serializeType = model.SerializeAll
        }

~~~
buzzerbetrayed
How is this not imperative verbosity?

Not to mention you are mutating an already assigned variable. You run in to
problems when you want to know the type of serializeType and you look at the
first assignment but don't see that there is a second one.

~~~
masklinn
> You run in to problems when you want to know the type of serializeType and
> you look at the first assignment but don't see that there is a second one.

Go is statically typed, so the type of serializeType doesn't change, only the
value.

------
dbt00
Go's certainly not perfect but I usually find it more productive than java or
C++ for equivalent problems.

For 2, I hate this example. Code that returns or takes booleans that requires
reading a comment to understand the value is super error-prone to use. Don't
write textually ambiguous interfaces in any language. I just haven't seen this
particularly be a problem.

#3 Re: checking errors, we wrote a trivial go vet plugin in house that checks
for that.

sort.Slice is probably new since this was written and is way better than
sort.Interface if you're sorting a slice.

Better vendoring and generics are finally acknowledged to be issues and
solutions are coming. Hooray.

------
gerbilly
My one line take on this:

You don't use Go for the language design, you use it for the tooling.

~~~
Boxxed
100% agreed -- it's crazy to me how much stuff you can just sweep under the
rug when you have fast compilation, a decent debugger, static binaries, and so
on.

I always tell people, "I love everything about Go except for the language."

~~~
apta
> have fast compilation, a decent debugger, static binaries, and so on.

See Java[1], C#[2]. Both have good compilation speeds (which don't really
matter when you have incremental compilation anyway), as well strictly
superior debuggers.

[1] [https://quarkus.io/](https://quarkus.io/) [2]
[https://docs.microsoft.com/en-
us/dotnet/framework/tools/ngen...](https://docs.microsoft.com/en-
us/dotnet/framework/tools/ngen-exe-native-image-generator)

~~~
Boxxed
Oh thanks, haven't heard of those languages.

------
solidsnack9000
Really enjoyed the same author’s _Java for Everything_ :

[https://www.teamten.com/lawrence/writings/java-for-
everythin...](https://www.teamten.com/lawrence/writings/java-for-
everything.html)

------
amedvednikov
I created a new language [0] that is very similar to Go, but it fixes many
things people often complain about, including all of the points in this
article (except #2, but I don't think it's a drawback, really).

It got lots of attention in a couple of months since the public release, and I
often hear people say that they feel like this is "Go done right".

It'll be open sourced by June 20.

[0]: [https://vlang.io](https://vlang.io)

~~~
jsjolen
If the size of a struct is changed through hot-code reloading then how does
the runtime react?

~~~
amedvednikov
Only function bodies can changed.

I don't think it's possible to modify structs on the fly.

Maybe it is, I need to think about it/do research.

~~~
jsjolen
Don't worry, it pretty much isn't possible to do so without semantics which
will basically make your program "drift" during run-time away from what a
newly compiled program would do.

EDIT: Assuming inlining and call-by-value struct is a possibility.

------
altmind
There's a good website documenting go quirks:
[http://devs.cloudimmunity.com/gotchas-and-common-mistakes-
in...](http://devs.cloudimmunity.com/gotchas-and-common-mistakes-in-go-
golang/)

Some of the problems are really annoying and artificial such as "declared and
not used/unused imports" trying to push golang opinion on code quality

------
nilsocket
Most of them are silly reasons.

The actual problems like versioning, error handling and generics (may be) are
being worked on.

I have seen many new learners find it hard to learn what packages mean, and
how about teaching them _private_ , _public_ , _static_ , ...

------
Skunkleton
My biggest issue is how nil works with interface types. If nil gets cast to an
interface type, you end up with something that doesn't equal nil.

------
Animats
Being able to ignore return values is something that C had before they had
function prototypes. The compiler didn't know if something returned a value,
so it couldn't check. There's no good reason for that misfeature in a newer
language.

Go apparently does it that way to make "defer" work.[1]

[1]
[https://github.com/golang/go/issues/20803](https://github.com/golang/go/issues/20803)

~~~
Ace17
When was the last time you checked the return value of 'printf' ?

Would you consider it a good thing to be forced to do?

Moreover, there are functions for which "not ignoring" the return value isn't
the same as "checking it" (e.g malloc, fopen, etc.).

(CppCon about error handling:
[https://www.youtube.com/watch?v=GC4cp4U2f2E](https://www.youtube.com/watch?v=GC4cp4U2f2E)
)

------
lamida
I don't understand with the claim source file with name i_love_linux.go
wouldn't compile in mac. I tried it and it is fine.

------
jasonhansel
_insert rant about how you need generics for functional programming here_

~~~
masklinn
Nothing a preprocessor and a smattering of syllabics can't fix.

------
sriharis
O hey, there's a subreddit dedicated to this:
[https://www.reddit.com/r/gobashing/](https://www.reddit.com/r/gobashing/)

------
SomeOldThrow
Why doesn't go enforce using return values (or explicitly swallowing them)?

------
ajross
From the very first item:

> Idiomatic Go uses shorter names like u, but I stopped using one-letter
> variables 35 years ago when I left TRS-80 Basic behind.

Ignorant snobbery. Skip.

------
mavelikara
(2016)

~~~
dang
Added. Thanks!

------
Otnix
Golang is difficult to learn especially for new programmer.. less support
community

------
trpc
it's a mediocre language, in fact it's the most mediocre language I have ever
seen, that is being pushed by managers who want to lower hosting costs and
faster time to market with good runtime performance.

~~~
hu3
\- lower hosting costs

\- faster time to market

\- good runtime performance

Looks good to me.

~~~
trpc
good if you're the manager not if you're the dev

