# The Value in Go's Simplicity


After using Go for a couple years, I've really come to appreciate its
simplicity. I started writing Go at work a couple months ago, and have found it
really easy to iterate on -- much more so than Python and Java.<!--more-->

As the Go community celebrated its
[10th birthday](https://blog.golang.org/10years) I was thinking about what makes
Go unique. I think a lot of the real power of Go has come from the philosophy of
its designers: There's a strong emphasis on forward compatibility, the language
doesn't have flashy features that hurt readability, and it comes out-of-the-box
with everything you truly need (a basic test library, solid networking and
synchronization primitives, and templating, to name a few).

## Forward Compatibility and Dependencies

In my opinion, of recent languages, Go has the sanest versioning and dependency
story. I haven't had a single breakage due to an update in Go. That is
significant. Over a similar time period, I've had projects break due to Rust's
APIs changing, the infamous Python 2-to-3 transition, and, to be frank, I'm
surprised if any of my old JS projects after an `npm upgrade`.

With Go, I've noticed that libraries tend to be stable -- almost worryingly so.
In Python- and JavaScript-land, if you see a library that hasn't been updated in
3 years, that's a sign of death. In the Go ecosystem, you're probably OK to use
it. What is seen as stagnation or neglect in other communities is often a sign
of resilience in Go.

I've also noticed that in Go I need fewer dependencies, and my dependencies
themselves have fewer dependencies. Go doesn't have a culture of exporting
as-much-logic-as-possible to external dependencies. Code duplication is more
acceptable in the Go community than elsewhere. This can be frustrating.
Sometimes, you just want a good library that performs some type of sanitation or
parsing. Many times, you'll need to write that functionality yourself, or
copy/paste it from a StackOverflow answer. Generally I think this is a positive.
Fewer dependencies means fewer things that break while you let a project sit
idle for a couple months.

Now, this might be a bit unfair to other language communities. Rust hasn't
reached the level of stability that Go has, likely because it isn't as mature a
language, but it's trending in that direction. Python 3 _itself_ has been
forward compatible, and I'd hope that the Python core devs learned their lesson
going forward about hard breakages. I don't have much hope for Javascript in
this regard but... uh... \*something\* \*something\* WebAssembly and ES10 will
fix all our problems.

Alas, Go's dependency system is not without drama. For a while, the fracturing
of `dep` and `glide` was really annoying; and, while Go Modules are great, the
community still hasn't reached 100% adoption. Before Go Modules, the requirement
to keep everything under your `$GOPATH` was so annoying that I held off diving
into Go for years. Things are better now and show signs of improvement.

As far as forward compatibility, any Go code written since Go 1 was released is
[guaranteed](https://golang.org/doc/go1compat) to work until Go 2, at some
indefinite point in the future. That's a strong commitment that, at least so
far, has been really positive to my use of the language.

## "You Ain't Gonna Need It" (But you might want it)

After using Go for a while, I reached a point where I wanted some extra features
that the language simply doesn't support. Generics was the big one for me, as I
think it is for many others. Look, I'm repulsed by C++ templates as much as the
next person, but having basic collection class generics isn't that much to ask,
right?

The only two generic (ish) data structures that you get out of the box are
arrays (`slice`s) and dictionaries (`map`s). Want to write your own data
structures? Well, you'll either have to make them specific to certain types, or
you'll be staring at a field full of `interface{}`. There's a time and a place
for both approaches, but... sometimes I wish I could just import a type-safe
generic bidirectional map, for example.

Go is ["You Ain't Gonna Need It"](https://www.martinfowler.com/bliki/Yagni.html)
taken to the extreme. _Need_ is the operative word here. You won't _need_
generics, but you will almost assuredly want them. Ditto syntactic sugar for
error handling, functional programming, and operator overloading.

As the cliché goes, sometimes less is more. With the exception of
[named return values](https://tour.golang.org/basics/7), I can't think of any
[footguns](https://en.wiktionary.org/wiki/footgun) that have been added to the
language. If nothing else, its impressive how much restraint the Go core
developers have shown against the swarms of developers asking for, say, generics
in Go. The hazy future of [Go 2](https://github.com/golang/go/wiki/Go2) is
really exciting to me, as I'm looking forward to seeing what an idiomatic "next
generation" Go will look like.

## Just Enough Batteries Included

For the use cases where Go shines, it comes out of the box with pretty much
everything you need.

`go test` is a great, albeit basic, framework for testing. No need to become a
domain expert in `JUnit`, or choose between `nose` and `unittest`. For
convenience, there are testing assertion libraries like
[`testify`](https://github.com/stretchr/testify) that you can pull in, but "you
ain't gonna _need_ it".

Similarly, Go's `sync` package covers most synchronization primitives that you
could reasonably need, `http` provides a production-ready HTTP server and client
(even supporting HTTP2), and there's enough goodies in the `encoding` package to
shuffle data around in `json`, `xml`, `csv`, and a number of other common
formats.

## Formatting, Formatting, Formatting

Finally, I'd be remiss if I didn't mention `gofmt`. I'm a bit of a nitpicker
when it comes to formatting. I don't particularly care _which_ rules are
applied, but I care a lot about consistency. Go's internal formatting tool,
`gofmt`, is adopted widely by the community and provides just enough consistency
that your Go code "looks" idiomatic without feeling like you're being suffocated
by a linter.

Personally, I've found that reading open source Go code is a _lot_ easier due to
`gofmt`. Each project still has its own way of doing things, but every project
follows the same formatting conventions. Aesthetically, this makes me happy.

---

So, I like Go. There was also a time that I was super enthralled by the
[_Zen of Python_](https://www.python.org/dev/peps/pep-0020/) and would turn my
nose at other languages. I'm looking forward to a strong continued future of Go,
but I could definitely see myself jumping on the Rust bandwagon once that
language settles a bit, because I do love me some functional-ish programming.

For now, I'm a Gopher.

