
Why I love Go - dimonomid
https://dmitryfrank.com/articles/i_love_go
======
w8rbt
Nice read. I like Go a lot too.

As to the minimalism in Go, I wish it came with a few more default data
containers.

Sorting a map by using a slice gets old after awhile. Why can't I pick a
sorted tree based map (like std::map or std:set in C++) or an un-ordered hash
based map like std::unordered_set, etc.? Why do the containers have to be so
minimal too?

This just leads to people rolling their own and many times, that leads to poor
performance and other issues which ultimately reflect poorly on the lanaguage.
I've seen more string implementations in C than I can count. Most of them were
bad. I hope Go doesn't end-up being like that.

~~~
logicallee
>This just leads to people rolling their own [containers]

Nah, Go was careful to make that impossible. (You know exactly what I'm
talking about, I'm not going to come out and say it. What one, specific thing
makes rolling your own container in Go literally impossible?)

~~~
Waterluvian
Classes (inheritance)?

(I'm actually guessing... This isn't my domain)

~~~
dmoy
I'm guessing they meant generics? Also not sure.

~~~
kasey_junk
They meant generics. But it’s not impossible, it’s tedious.

------
pfarnsworth
After working with it for a year, these are the things I don't like about Go:

1) No constructors. When I create a struct, without a constructor, I can't be
100% if certain fields are populated or not. With a constructor, I could force
this. With a large number of people working on a code base, you can't assume
anything, unfortunately, but without a constructor to force exact data in a
struct, it makes it more tedious to be sure.

2) Error handling is ugly and tedious. Not being able to get the type of an
error makes it a lot more inconvenient. At least in our codebase, errors are
almost string parsing, it's ridiculous.

3) Nil map vs empty map is a very strange thing to keep in the code. Why even
allow this distinction?

4) Named return parameters are really stupid. This is another thing that
doesn't fit the philosophy of what I understand Go to be. It forces a bunch of
verbose opinionated rules on us, but then allows named return parameters which
causes confusion.

5) It's very hard to tell the difference between package names vs structs.
Luckily Gogland allows you to change the color for package names so this helps
me out tremendously, but there should be a better way to differentiate without
relying on your IDE.

Overall it's okay but nowhere near perfect and has some really weird
deficiencies. The company I work for uses Go with dependency injection which I
hate and I think is very ugly but a paycheck is a paycheck.

~~~
camus2
> 4) Named return parameters are really stupid. This is another thing that
> doesn't fit the philosophy of what I understand Go to be. It forces a bunch
> of verbose opinionated rules on us, but then allows named return parameters
> which causes confusion.

They exist because go really has exceptions. The only way to "catch" and
modify variables in the "catch" before they are returned is to use named
return values. You can't return anything from a panic/defer/recover directly.
Error as value are just a convention.

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

~~~
barsonme
They also help clarify what the return parameters are. It can be helpful if
you have multiple if the same type (e.g., func Foo() (int, int))

------
flavio81
So far I fail to understand the excitement with Go.

Error handling in go feels like going back to 1960s programming.

Garbage collection is already implemented with high performance in Java and
other platforms, what's new? You can use GC with different strategies in C++
as well, if you like, the libs are there. There are many libs to get
dynamically managed memory in C. But the author wants to program for embedded
devices and my choice there would be to avoid dynamically managed memory for
the most part.

Coroutines and tons of different concurrency and multiprogramming and
parallelism paradigms and strategies are already available for most mainstream
languages.

Syntax in Go looks like a poorly done copy of Algol-68 (1968, and
-surprisingly- a more powerful language.) Why?

At least if they would have went with s-expression syntax, they would have
enabled metaprogramming and this would have solved some of the problems with
missing features.

As for use in embeddable devices, the author discards D and other languages
for lack of portability to other platforms; but AFAIK embedded devices
programming goes to very low level details and thus I can't think how a code
that is tied to the specific hardware would be portable, no matter what the
language is.

I thought Google had smarter language designers. At least Mozilla did a decent
effort with Rust. Perhaps Google do have smarter engineers and they actually
use Julia, Lisp, and Smalltalk for Google's internal projects...

~~~
koffiezet
> Garbage collection is already implemented with high performance in Java and
> other platforms, what's new?

A simple language that can be used for both 'scripting' projects and larger
applications, natively, statically compiled, with a modern standard library
aimed at what a lot of "ops" development is currently in need of. Hence the
explosion of tools written in Go targeting that field. Maybe it's not suitable
for your applications, but there is clearly a market for this.

> but AFAIK embedded devices programming goes to very low level details and
> thus I can't think how a code that is tied to the specific hardware would be
> portable, no matter what the language is.

That depends on the type of embedded stuff. I wrote a ton of embedded code
targeting various embedded OS's on POS systems running m86k, MIPS, ARM and
other stuff. I was responsible for designing and writing a generic hardware
abstraction layer. It took considerable resources, but once streamlined,
porting to another platform took about 3 months (if the hw and
compiler/toolkit vendor were helpful, otherwise it could take years). It gave
us the massive advantage of being able to develop/debug/showcase the
application logic on a PC or on alternative hardware, and then finally target
the real hardware when the HAL was finished and work out some kinks there,
taking another month or so. So yes it's absolutely possible to write portable
embedded code.

> I thought Google had smarter language designers. At least Mozilla did a
> decent effort with Rust.

Given the adoption rate of Go in the ops field, which incidentally is what
Google needs a lot, I'd say they at least got something right.

------
diebir
"Go is a better* C" It seems like Go is propelled into popularity by people
discovering the joy of C/POSIX programming for the first time.

Some of us remember, however, why we left C behind (it does not work beyond a
certain degree of complexity). Why would I want to do Web programming in C? We
spent years creating better tools for this.

~~~
taneq
> Some of us remember, however, why we left C behind (it does not work beyond
> a certain degree of complexity).

Yeah, but it's pretty good for small simple projects, like the Linux kernel.

~~~
paulddraper
The Linux kernel has had innumerable man hours poured into it. (Estimated at
$3 billion to recreate.)

It's so large its creator invented a sophisticated VCS to manage it.

There aren't many projects like the Linux kernel.

------
0xCMP
I love Go, but there needs to be some work around dealing with the problems
the community is solving via code generation.

I feel like a lot of the things I find tedious about Go should be much easier
to generate somehow so I can get on with what I was trying to do. sqlboiler is
an interesting version of something that Go by-it-self can't provide without
code generation if you require not using reflection.

Otherwise, I like the language a lot. I mainly love it's simplicity to deploy,
good cli, and low memory foot print. I also like that it's very easy to read,
that the community is focused on "reading code", and that there are many good
libraries out there now in addition to the standard library.

Started looking at Scala recently, and I'll probably play around with it, but
it just seems Go is so much nicer to use for the kinds of projects I'm trying
to develop.

~~~
lobster_johnson
I wish Go could have "just-in-time" code generation.

Right now, we have the magical //go:generate comment, but since it requires
manual invocation of "go generate", artifacts can and do get out of sync with
the Go code.

It would much nicer if Go code could contain code that caused generation to
happen when the code was compiled. Adding the ability to execute Go at compile
time would be one possible solution, similar to Rust's custom derive [1]
support. As a use case, Rust has libraries that make extensive use of this
system, such as serde [2], which can automatically generate efficient, type-
safe serialization/deserialization code for structs (e.g. to/from JSON).

[1] [https://doc.rust-lang.org/book/first-edition/procedural-
macr...](https://doc.rust-lang.org/book/first-edition/procedural-macros.html)

[2] [https://github.com/serde-rs/serde](https://github.com/serde-rs/serde)

~~~
chimeracoder
> Right now, we have the magical //go:generate comment, but since it requires
> manual invocation of "go generate", artifacts can and do get out of sync
> with the Go code.

It's pretty easy to enforce that as a build constraint in your CI system; we
do that with our Go projects. If the output of `go generate` isn't checked
into git, the build fails. (Same if the code hasn't been formatted with
gofmt).

~~~
lobster_johnson
True, but you have to do it for every single project. We have tons of apps
that all need to manage little rules like this, it gets pretty exhausting
after a while.

~~~
ghthor
And NOT having to maintain little rules like this is one of the reasons I fell
in love with Go initially. Between gofmt and gofix, the go tooling just
works(tm) so danm well.

------
rcarmo
I agree that dependency management and GOPATH are two annoyances that need to
go away. GOPATH in particular is a constant pain when you work across multiple
machines like I do, and feels like a mandated anachronism/catechism (your
workspace must be like we want it to, and we don’t care about your own
methods).

On the other hand, lack of proper vendoring, version pinning and getting
random versions of libraries off GitHub makes a lot of people anxious about
long-term reproducibility.

Like a peer of mine once said, “maven is forever. They don’t call things
‘artifacts’ for nothing, I can even do archeology in my dependencies”.

~~~
gnur
I actually like the GOPATH. It has forced me to order my code correctly, I now
have a single ~/code directory where all my checkouts reside.

I created a small bash script (called giclo) which automatically places
checkouts of git repo's in the correct ~/code/src/HOST/USER/REPO directory,
super convenient and very well organized.

------
Will_Parker
> On the cost of some repetition here and there, it makes programs look very
> explicit, which helps readers to understand the code better, instead of
> wondering: can the exception be thrown here or not?

I don't get this. In practice, most functions end up having an error result by
convention, so the answer to "can the exception be thrown here" is always
"maybe", which is the same as the answer would be to any function call in a
language with exceptions...

~~~
beefsack
Also, even without exceptions, it's possible to have explicit error handling
without so much boilerplate. Rust's `?` operator achieves the same thing as Go
without filling your code with conditionals and return statements.

I do appreciate the difficulty in balancing simplicity and verbosity, but
there are a handful of cases in Go where I wish they added some complexity to
make the code significantly more terse.

~~~
0xCMP
Adding some kind of optional into Go would make things much easier. It's a
cleaner version of the same thing.

~~~
valuearb
Well, Lattner did propose adoption some of Go's concurrency models in Swift.
Then you already have optionals, a faster garbage collector, and a much deeper
language.

[https://gist.github.com/lattner/31ed37682ef1576b16bca1432ea9...](https://gist.github.com/lattner/31ed37682ef1576b16bca1432ea9f782)

You just don't have a big community building server tools and libraries around
it yet.

~~~
hamandcheese
If swift had a better concurrency story I would be all over it. The general
vibe I get though (as an iOS super noob) is that concurrency patterns were
already established back in the ObjC days and there’s little incentive for
Apple to change it.

I sure hope I’m wrong!

------
s4vi0r
It's so strange seeing people who write these sorts of articles constantly
praise Go's error handling. In what world is doing the whole if err != nil
thing every 30-50 lines not ridiculous?

I get that goroutines are great, but that really seems to be all Go has going
for it. The GC sucks, error handling feels like something from a bad language
designed in the 70s, missing generics, math library is awful, Rob Pike being
super opinionated, etc.

~~~
Xeoncross
> doing the whole if err != nil thing every 30-50 lines not ridiculous?

It's more like every 5 lines. I love it as every error is handled correctly
and in scope. No error is left behind. Most languages I've used devolve into
the GLOBAL MASTER DEFAULT HANDLE ALL ERRORS which is just gross.

~~~
lobster_johnson
In practice, scoping becomes an issue because "err" sneaks in everywhere.

For example, consider:

    
    
      foo, err := getFoo()
    

Now your scope has an "err" and you open yourself to logic errors such as:

    
    
      foo, err := getFoo()
      ... do stuff ...
      if errr := makeBug(); errr != nil {
        return err
      }
    

Spot the (heh) error? It's caused by ":=" allowing variables to be reassigned.

You can avoid this dangerous pollution, but it's super ugly:

    
    
      var foo *Foo
      if f, err := getFoo(); err == nil {
        foo = f
      } else {
        return err
      }
    

(You have to have the return in the second branch, otherwise "go vet" will
complain. Sigh.)

I have lots of these, and they're not helped by the fact that Go has no type-
level mechanism to guard against the misuse of multiple-return values. That
is, in the above, either "foo" or "err" are usually set, and if "err" is set,
it means "foo" isn't. But the type system doesn't prevent you from
accidentally ignoring "err" and using "foo", or vice versus. This gets even
worse if the func returns a (non-pointer) struct as its value.

The fact that Go allows shadowing (exacerbated by the convention of using
"err" as every single error variable) and promotes the reuse of variables
(e.g. the above ":=", or declaring "err" outside a loop) also means it's super
easy to assign the wrong thing.

All of the above are my single biggest source of bugs during development.
That, and how accidentally using nil/zero values, including the damnable nil
map/slice cases.

"go vet" (whose shadowing check is disabled by default (!)) and the various
linters only go some ways towards helping here. The errcheck linter (which you
can enable through gometalinter) is absolutely essential.

~~~
xenoncross
There are real problems, and not real problems. I'd classify this as a not
real problem. How hard is it to name errors differently when it would be a
_real_ problem? A few keystrokes.. and BOOM! Problem solved.

I wonder what is the correlation between volume of complaining about minutia
such as this compared to real life ability and level of accomplishment.

~~~
lobster_johnson
When you work with Go every day (which I've done for last two years or so),
small problems become significant annoyances.

It's a decent language, but it's also a deeply flawed one. I could mention
many other, bigger flaws, but this particular discussion was about errors.

Also, it's actually okay to debate minutia. Dismissing something as "not real
problems" is, well, dismissive.

------
jabbanobodder
I often fell the same way about flag, recently I started using [go-
args]([https://godoc.org/github.com/alexflint/go-arg#example-
packag...](https://godoc.org/github.com/alexflint/go-arg#example-package--
MultipleMixed)) and so far I've found that it works a bit smoother.

~~~
incompatible
I like [https://godoc.org/github.com/jessevdk/go-
flags](https://godoc.org/github.com/jessevdk/go-flags), since it also supports
environment variables. It's nice to be able to get configurable defaults from
the environment and still be able to override them on the command line.

------
greenhouse_gas
Personally, I don't like Go. I wish my projects needed Rust's speed, or its
safety, or its engineering powers.

But I don't. For simple parsing or number crunching, Go is just right.[1]

I find the fast prototyping, the wonderful IDE environment (VSCode, vim), and
the community to be _so good_ that I don't need anything else.

There was a time I thought of learning Python[2] or Rust, but found both
lacking.

[1]. Sure, I wish I was smart enough to get a job working on Quantum, working
as a kernel dev, or in fintech where every nanosecond counts. But I'm not. The
Rust community is great, there's a lot of help out there, and it seems like an
amazing and cool language.

[2]. I tried it out a bit. My main issue is that it doesn't (didn't) have
nearly as good of an IDE community (PyCharm is practically the only good IDE
for Python, and in the bit of time I spent with it, I found it much less
powerful than their Java IDE) revolving around it.

~~~
didip
What part of Go you don’t like?

~~~
greenhouse_gas
safety, immutability, lack of functional behavior, Algebraic data types.

All the fun stuff.

~~~
sp33der89
Have a look at Nim([https://nim-lang.org/](https://nim-lang.org/) ). It
doesn't have great IDE support, but VSCode plugin works well enough and the
language has a lot going for it.

Edit: posting this because I'm in the same situation. I like Rust/Nim/Elixir
but Go has a great productive ecosystem even though the language is quite
"barebones".

~~~
greenhouse_gas
I don't know about its IDE support, but it doesn't have as large of a
community as Go.

------
froderick
This is one of the more measured cases for golang I have read.

When it comes to my default set of tools, I gravitate towards dynamic,
expressive languages that provide greater leverage rather than ones with fast
startup times, c-like speed, native binaries, etc.

That said, when you need those things, I agree with this guy--golang has been
a far better experience for me than any other language of its ilk. I'm not
claiming it has magic powers like rust or a sentient type system like haskell,
but I spent hours learning go fundamentals, and days figuring out how to get
real work done with it. I can't say that for many other languages with go's
compile and runtime capabilities.

------
partycoder
Go is OK, but it was a bit mean of the authors to hijack an existing name for
a programming language.

This was the pre-existing language:
[https://en.wikipedia.org/wiki/Go!_(programming_language)](https://en.wikipedia.org/wiki/Go!_\(programming_language\))

Google reacted to the criticism saying there are many products named Go.
Well... that's a 2-way street. If there are many products called Go then why
picking that name in particular?

~~~
paulddraper
> then why picking that name in particular?

The rest of your criticism may be valid, but I would think that this part is
obvious:

(1) It's a word.

(2) It's short.

(3) It resembles Google.

------
1_2__4
For me the biggest PITA lately with Go is dealing with json. Exhaustively
listing every potential field in order to type it is maddening.

~~~
chimeracoder
> For me the biggest PITA lately with Go is dealing with json. Exhaustively
> listing every potential field in order to type it is maddening.

Sounds like gojson[0] would make your life a lot easier - it automatically
generates the struct definitions for you.

[0]
[https://github.com/ChimeraCoder/gojson](https://github.com/ChimeraCoder/gojson)

------
stevefan1999
As a C-C#-C++-Java-ES2015+ guy, I found it hard to read and write in Go. :(
Same problem goes for Python. (Not Ruby and CoffeeScript tho, I don't know
why)

I don't think I'm alone. I need some hugs.

~~~
Traubenfuchs
You don't need hugs, you need the realization that the knowledge in the
languages you mentioned will continue to stay relevant and continue to make
you employable in the next ten years.

------
valuearb
As I read this it made me wonder why I was still using Javascript to write my
server code. Thing I always hated about it was the lack of types, and
practitioners bleating to "write unit tests" instead. So much less efficient
and effective. Even Typescript doesn't seem like much of a fix.

Go sounds like Swift, strongly type compiled languages. Go has better
concurrency features and likely compiles faster (I mean anything has to
compile faster than Swift).

Swift still seems to have better, faster garbage collection, better language
features such as generics, and optionals make error handling and writing safe
code much easier.

But Swift doesn't have the community and infrastructure around server
development that Go does. I think I'm giving Go a go next project.

~~~
thatswrong0
It’s funny because I use JavaScript every day on the front end and often have
to write backend in Go.

I honestly don’t think Go does enough to it to make it worth using over
something like JavaScript. You still have to write unit tests and integration
tests. It’s strongly typed, sure, but it’s type system isn’t robust and doesnt
really help you that much, and it just feels.. outdated. Every other line of
code is “if err != nil”. Nil pointer exceptions are.. still a thing. Yuck.

Typescript has a far more expressive type system than Go.

~~~
dimonomid
Not sure what do you mean by "its type system isn't robust".

------
Kototama
> Go is a better C

Setting the scale for language comparison to C (or Python) is setting the bar
pretty low. There are so much better languages out there.

~~~
afghanPower
Better than C and Python.. Examples?

------
spyspy
> no way to know whether the flag was given by the user or the default value
> was assumed implicitly

I'm struggling to find a need for this. Flags define behavior, who cares if
the behavior is explicit or implied from inaction?

~~~
openasocket
It matters if there's no way to have a flag without a default. If your flag
doesn't have a clear "user didn't supply anything" default it can be annoying

~~~
ecnahc515
It's always possible to define a custom flag type to handle this. It's
definitely what I would consider niche however, since usually you don't care
about set/unset just whatever the value is, default or not.

------
zaarn
Personally, I've written a lot of stuff in Go, it might not be a perfect
language but it's certainly the most fun one. I can sit down, write 1k LOC and
have implemented something that I can look at in 10 years and still know what
I'm doing.

It has it's downsides but I love it despite those, errors could be better but
it's mostly fine and I'd love some generics so I could optimize my storage
structures (though by using a backing array and referencing indices helps a
lot)

------
zxy_xyz
It's a no-go for me. I like the lang but I make games and don't like GC. Jai
seems to be in the se direction as Go in other aspects though

------
dimpadumpa
Go is sooo nice. Best thing ever, that google done.. Otherwise Google is not
my best books at all..

------
mk89
> go is a better C

I am not experienced enough with go, but I would say the same. Not better
maybe, but the modern C.

------
rishav_sharan
I like go, but i can't stand its package management

------
majewsky
TIL that Bram Moolenaar has more than one project.

