
What will be the legacy of Go? - clessg
http://dave.cheney.net/2015/11/15/the-legacy-of-go
======
Animats
Go was written to solve an internal problem at Google. Google needed efficient
server side applications. Python was too slow, and C++ was too hard to write,
too buggy, and a pain for string work. Google then developed good-quality
libraries for all the things one needs for such applications. That made it an
excellent language for server side work.

As a language in general, Go is practical and mediocre. This may be a
strength. Go lacks generics, and thus has to over-use introspection. In
practice, while "interface{}" implies extra run-time work, it tends not to end
up in compute bound code. (Two notable exceptions: sorting and database
access.) So that turned out to be less of a hassle than expected. Also, from
Google's internal perspective, they're mostly using their own data structures,
and type-specific code may not be a big problem.

Go's approach to concurrency hand-waves too much on the data sharing issue,
and has soundness problems, but at least the language talks about concurrency
and has some reasonable primitives. C and C++ don't even provide syntax for
talking about concurrency.

------
nickpsecurity
The C section is so wrong it's unbelievable. Or why I created the Pastebin
below. There were plenty of good languages before C, not just asm. C wasn't
designed: a tweaked BCPL and B to work with PDP-11. C wasn't even meant to be
portable.

[http://pastebin.com/UAQaWuWG](http://pastebin.com/UAQaWuWG)

Helps to understand what it is exactly and then the rest (like ditching it)
becomes more obvious. P-code was probably the first portable, assembly
language with good results. Or LISP from the functional side.

~~~
gajjanag
Thanks for the illuminating link.

Nevertheless, I unfortunately do not see an easy solution in the near future
that avoids C/C++ much as I would love to ditch them. Let us leave aside the
question of legacy code and focus on future systems projects.

General issue: C and C++ have an advantage in the sense that we understand
their many problems well due to their long history, and they have formal specs
that are far more carefully written than most others, where documentation is
spotty and formal specs are often lacking. Example: I have not studied Rust
closely, but it seems to me that there are sections that essentially must be
placed under "unsafe" for performance or low level access. The oft-repeated
claim is that it minimizes the surface, since it localizes the unsafe
sections. I have not seen any hard, formal guarantees in either the spec or
implementation as to what is precisely meant by this. I am very interested to
know how I can reason that the unsafe section has zero side effects outside of
it. Such a statement in general must be false, since the unsafe block clearly
communicates with the rest of the program, else it is dead code. And if the
interface is sandboxed (an imperfect solution), then it implies some kind of
performance penalty across the barrier, implying additional cognitive load for
a developer since he/she has to reason about the possible performance impacts
for such things, among others like array bounds checks. Lastly, if the
guarantee regarding the extent of the "unsafe" block is as complicated as I
suspect it to be, the load is increased further. Of course, the load comment
is really relevant to Rust vs C and not Rust vs C++.

Specifics: 1\. Go - garbage collector, large runtime/binary sizes, portability
issues (AIX: [https://groups.google.com/forum/#!topic/golang-
nuts/IBi9wqn_...](https://groups.google.com/forum/#!topic/golang-
nuts/IBi9wqn__FY)). 2\. Rust - too new, general points above. 3\. D - lacks
the same energy as the above projects, so likely fares worse than the above.
Furthermore, due to its closer ties to C++, its rather incremental nature
resulted in a significant loss when C++11/C++14 came around. 4\. Others - too
many to list, focused on above due to their frequency on Hacker News.

~~~
pcwalton
Focusing on Rust "unsafe" as some sort of way to ding its safety drives me
crazy.

"unsafe" blocks in Rust is designed to be just like the compiler backend. We
could have built things like Vec::new and vector indexing into the code
generator, like Go or Java did. Then we wouldn't need the "unsafe" construct
in the language (except to interface with kernel32.dll and/or syscalls). But
that would make our lives harder _for absolutely no extra safety gain_. It's
precisely the same thing as implementing things in the compiler backend, but
it's _safer_ than doing that, because we get to write code in a stronger type
system than that of raw LLVM.

More succinctly: What makes the compiler backend safe while unsafe blocks are
not? Can you name one thing that makes the compiler backend safer than code
written in unsafe blocks?

~~~
gajjanag
I did not "ding" it, but asked for an honest, transparent response if
available. It can only help the Rust community by making such things clear. I
focused on it as it is what I got probing Rust since after all there can be
"no free lunch".

The compiler backend may be viewed as a smaller component that needs to be
trusted. General code lies on top of it, and there is a big difference due to
code volume.

~~~
pcwalton
I don't understand what "there is a big difference due to code volume" means.

~~~
gajjanag
I was referring to all usage of Rust by clients across the world versus a
single compiler and reference standard library. Many of these clients will
need "unsafe" blocks, and the combined length of these "unsafe" blocks will
exceed that of the standard library and compiler assuming Rust adoption is
high.

This is what concerns me: I wished Rust's "unsafe" blocks could have been
exclusively confined to some things in the reference language compiler and
standard library. Unfortunately, it seems like many reasonable systems
applications still need access to unsafe blocks for reasons of performance,
low level access, etc and such needs are not uncommon given the target systems
audience.

~~~
kibwen

      > I wished Rust's "unsafe" blocks could have been 
      > exclusively confined to some things in the reference 
      > language compiler and standard library.
    

This sadly isn't possible in a language at the systems level. If you don't
provide an escape hatch then users will just use the C FFI as an escape hatch,
which results in far more potential unsafety than Rust's `unsafe` blocks.

------
threeseed
I think Go will ultimately be remembered for reaffirming the importance of
single binary deployments.

The world of deployments e.g. build scripts, containers, extravagant tools are
all unnecessary with Go. And I suspect future languages will learn from this.

The language itself not much. It doesn't offer anything new that Java 1.0 with
Quasar doesn't already have.

~~~
farrisbris
I think the single most important 'thing' go offers is his third point. The
removal of the thread. The ability to very easily run multiple concurrent
pieces of code cannot be understated. I have my grievances with go as i do
with every other language, but what makes me more or less automatically start
most new projects in go is that i know that at some point i will probably be
sending the same http request to N servers or some variation of a similar
task, and even if it can be made to work in any other language, the ease of
which it is done in go keeps me coming back.

As an aside i think the composition over inheritance argument deserves a
mention. The io.Reader and io.Writer interfaces () and their close friends
io.ReadCloser, io.ReadWriter etc) have completely transformed how i approach
tasks that involve shifting data through a number of whatevers.

~~~
ridiculous_fish
What do you mean by "removal of the thread?" Go is multithreaded and is
vulnerable to classic thread-safety issues, like races and reentrancy.

~~~
mkup
Go runtime library contains user-space scheduler which maps lightweight Go
threads to heavyweight OS threads in M:N manner. By the way, Go runtime
library allows running user code in only one OS thread per process, all other
OS threads must be in the state of blocking system call. So, no mutexes /
interlocked instructions are required to access global data from goroutines,
but this comes at the cost of reduced parallelism compared to C/C++ (which
author of original article seems to be unaware of).

~~~
NateDad
Wow, uh no. You're 100% wrong, unless I'm misunderstanding you. You can
absolutely have user code running on N threads simultaneously (where N is the
number of cores of your machine). And you definitely do need mutexes.

Your statement holds only if GOMAXPROCS is 1, which granted used to be the
default, but was always able to be increased, and the default now is the
number of cores on the machine.

~~~
mkup
Ah, now I see these things changed recently. I wrote original comment because
at the time of Go 1.1 or 1.2 my colleague wrote racy code which accessed
global variable without mutexes. I tried to educate him to use mutexes, by
reducing his code to the minimal version demonstrating race condition, but
failed. Then I digged into the source code of Go runtime library and
discovered that only one thread could be in the running state at any moment
(other threads could be in the state of blocking system call).

So, things changed since that time. OK, nice to see Go evolves. Interesting,
how many code in production got broken during upgrade to Go 1.5 due to this
backwards-incompatible change. Overall situation seemed totally reasonable to
me at that time: Go is a language for average programmer, so it should prefer
safely over runtime performance; and coding cowboys who are comfortable with
mutexes, interlocked instructions, memory barrier instructions, and lock-free
data structures will use C/C++ anyway.

~~~
tcard
But that wasn't true either at the time of Go 1.1, nor ever I believe. It was
the _default_ behavior to have a single core running at a time, but you could
just tweak that with the
[GOMAXPROCS]([https://godoc.org/runtime#GOMAXPROCS](https://godoc.org/runtime#GOMAXPROCS))
variable, documented everywhere. (That's what changed in Go 1.5; now the
default for GOMAXPROCS is the number of cores in the machine.)

------
Recoveringhobo
The legacy of Go will be a movement by many developers to statically typed,
compiled languages after spending many years with Python, Ruby, and
Javascript.

Although it is not groundbreaking, it will continue to be used because it
takes the ease of dynamically typed languages and gives you fast compilation.

------
xiaoma
Perl: the language that showed us brevity.

Despite all its various layers of madness, it made a generation of programmers
more productive than they'd known was possible. Tasks that used to be major
undertakings often boiled down to simple scripts. Python, Ruby and many other
languages since have borrowed from and built upon the brevity that Perl first
showed us and it's unlikely that people will ever go back to the verbosity
that used to be common for text processing and sys admin tasks.

------
vorg
> Go is still young, with a long productive life ahead of it [...] compared to
> the number of people who will use Go during its lifetime, we are but a tiny
> fraction

An assumption lurking in the last paragraph. Remember JavaFX and Dart, both
languages backed by large corps who then pulled their support. Go could be at
the peak of its popularity, about to tank. We don't know.

~~~
JulianMorrison
I'm thinking of Turbo Pascal for DOS. It was very popular, and then it sank to
obscurity almost overnight, basically because it didn't have any answer to
"how do I write a Windows program in this?" Its niche had been eliminated.

I don't think Go will vanish unless "network servers that run in text mode on
unix" somehow stop being a thing. There is no Google product whose change of
strategy could strand Go (unlike the others you name). If somehow all
computing moves to phones and tablets, it could be stranded, but I can't
imagine that happening.

~~~
pcunite
Was it not reborn as Delphi? It was always Pascal. But I do agree, a non-
visual service lang is probably a thing.

~~~
ant6n
Delphi was really not so bad. Back in High School we first learned with
Pascal, then Delphi. It was pretty simple to put together simple Windows GUI
Programs. Never really used it outside of school though.

~~~
hboon
> It was pretty simple to put together simple Windows GUI Programs.

It was one of the most powerful Windows (GUI) programming tool back then, and
easy to create beautiful UI components and had great third-party components
market. Plus it has incredible compilation speed.

------
petke
"I mean, who doesn’t want to be simple ? And what better way to frame a debate
as simple; good, complexity; obviously bad. Could we say then that simplicity
will be Go’s lasting legacy ?"

I think this misses the point. Complexity isn't bad. Only Incidental
complexity is bad. Inherent complexity exists in the domain itself and is
unavoidable. If this inherent complexity is not expressible by abstractions in
the core language itself. Then it must be expressed in libraries, or user
code, or in the way end-users configure and use the program.

Go is interesting because it created abstractions for concurrency in the core
language itself. Go is a more complex language because of it, but concurrent
programs user code is less complex because of it.

(On a side note C++17 is getting a more abstract version of go-routines.
Thanks Go.)

~~~
pjmlp
Co-routines go back to Modula-2 (1978) and first COBOL optimizing compilers,
Go didn't invent anything there.

~~~
frik
More recent inspirations: Win16/32 API has "Fibers" (used in WinWord), Lua has
coroutines.

------
lechuga
Minor nit re: Rails legacy. IMO a major reason it was so popular was because
of Ruby. It's certainly not the right hammer for every nail but the syntax is
one of the best to work with ever. Whenever I can find a project where writing
a little Ruby makes sense I use it. Because I enjoy it :)

While it's useful to me and dominates what I code in atm, I don't necessarily
like writing Go. Better than C/C++, sure, but I wouldn't go so far as to say I
enjoy it.

~~~
vinceguidry
Have you tried Crystal? I used to think I loved Ruby for its syntax, until I
tried Crystal, then I found out that Ruby's dynamic typing and the sublime
object model are just as important, if not more important, than the syntax.

------
frik
C, C++ and Go are going strong. All operating system kernels we currently use
are in C, as well as most low level drivers and libraries. Most PC client
applications are in C++ including most video games. Common web servers are in
C. They will be around for many more decades.

Go already replaces Java and dotNet as a leaner more suitable server language
in some companies. Nodejs and Go apps (+ JS in the web browser) replace older
CRUD web apps written in Ruby/Python/Perl. Most languages will stay around for
a long time, although a less popular for beginners.

Java and dotNet will have a harder stand. On the one hand dynamic typed
languages like Lua, Javascript and Hack/PHP with their JIT compilers are
already (almost) as fast and allow developers to be more productive while
still offering optional typing when/where speed matters. On the other hand new
static compiled languages get more approachable (Go, Rust, Swift), are faster
and use less memory.

Paradigm shifts surfaced exotic languages and trends. So Erland/Elixir, Go,
Nodejs and others are very popular for todays web services.

~~~
pjmlp
Java and .NET have AOT compilers so compilation to native code is not a point.

They have support for generics and FP like programming that Go will never get.

Go will never have the access to the system resources on Windows and Windows
Store like .NET does.

Go will never had access to Android frameworks like Java does.

Go doesn't have a UI toolkit like JavaFX and XAML.

All companies selling IoT SDKs are paring Java with C stacks.

Go doesn't have the IDE tooling support that Java and .NET enjoy.

Java and .NET having a hard time? Only if one is living in a bubble.

~~~
frik
Some of your info is a bit outdated.

Speaking of Go, it's appearently commonly used for server side services/apps.
Well the same can be said for Java and C#/F#/VBNet.

All applications we all use on the client side are C/C++/ObjectC/web apps.
(exceptions are maybe Eclipse/IntelliJ, mind that Visual Studio is C++). Java
on Android is an exception for legacy reasons (Google bought the Android
company; and we pay the price buy using 2x-4x as powerful hardware (CPU cores
& memory) comparing to iPhone to get similar UX & latency). Even the Win10
startmenu is still a C++ application for performance reasons. AOT is helpful
for certain execution paths like JIT and isn't magic. Even the Win8/10
calculator app has a loading splash screen, the FirefoxOS calc app starts
faster. XML based UI languages work, but aren't that great (e.g. resizing the
Win10 startmenu isn't what I would call responsive design in comparision what
we known from HTML5&CSS3).

Beside that you wrote a good comment above:
[https://news.ycombinator.com/item?id=10568915](https://news.ycombinator.com/item?id=10568915)

~~~
pjmlp
> ll applications we all use on the client side are C/C++/ObjectC/web apps.

Not every company is the same.

Since when does Apple have server frameworks for Objective-C?

WebObjects was re-written in Java.

My current customer uses everything native, with web apps just for small CRUD
maintenance tasks of a few DB systems.

> Visual Studio is C++

Visual Studio is a mix of C++ and .NET code, its UI infrastructure was
completely rewritten in VS 2010.

> Even the Win10 startmenu is still a C++ application for performance reasons.

Have you seen the code? How sure are you that it isn't .NET Native?

> Even the Win8/10 calculator app has a loading splash screen,

Anyone that knows WP dev, knows those splash screens are optional.

> the FirefoxOS calc app starts faster.

Which is behind WP and BlackBerry in sales.

------
catnaroek
> I think a strong contender could be a lack of inheritance; _Go took away
> subtypes._ [emphasis mine]

Go took away subtypes? News to me.

------
forrestthewoods
I'm not sure Go will have a legacy in 50 years. If you gave me even odds I'd
go with none.

~~~
johnmaguire2013
Care to explain why? This comment doesn't really say anything without an
explanation.

~~~
forrestthewoods
Most programming languages don't have a legacy. They're just forgotten. That's
the default. So far I've not seen anything from Go to make me think it will be
more than a footnote.

~~~
nzoschke
How about Docker and other tools in the container space?

Go is a great systems language. The stdlib is through and handling IO and
pipes is safe and fast.

Amazon is using as the mission critical ecs-agent that orchestrates their
container service.

Perhaps containers will be forgotten too. But my guess is that we will be
seeing some go binaries controlling very important parts of Linux and
distributed systems in the far future.

~~~
bluejekyll
Go is problematic as a systems language. Calling it safe is odd, when it's
glaringly allowed for Null. It's safe like Java is safe, which means that the
memory will always be safe to use, but the program will still die due to bugs
that a compiler could have helped prevent.

As a comparison Rust has no runtime, has no garbage collector, and is a pure
systems language, and also helps developers be truly safe. Based on my
experience with Go, I still don't understand where it fits, it's a compiled
language, but has a runtime and a GC. So it's somewhere between C++ and Java,
it's less verbose and faster to program in, but if that's the desire, than
perhaps the better choice will be Kotlin in the long run.

~~~
brobinson
> which means that the memory will always be safe to use

In another post [1], the author of the article claims that Go will not
"tolerate unsafe memory access".

A reference to a variable could be sent across a channel and nil'd from the
sending goroutine before being dereferenced in the recipient goroutine,
causing a crash. Doesn't this invalidate the "safe memory" claims, or are
concurrency-related memory issues not considered when making that claim?

[1] [http://dave.cheney.net/2015/07/02/why-go-and-rust-are-not-
co...](http://dave.cheney.net/2015/07/02/why-go-and-rust-are-not-competitors)

~~~
dbaupp
Dereferencing nil is not an unsafe memory access in Go, just like a null
pointer exception in Java isn't unsafe. Both are well-defined operations
(sure, they yield errors, but they do so with 100% reliability and complete
control), they're not undefined behaviour like in C or C++.

Unsafe memory accesses refers to things like accessing an array out-of-bounds,
or reading from a pointer that has already been freed. (I suspect a data race
could actually cause an array to be accessed out of bounds in Go, but I'm not
sure.)

~~~
brobinson
Thanks for the clarification! What if instead of the sender goroutine setting
the pointer to nil, the GC frees the object that the pointer was pointing to
before the recipient goroutine reads it? Wouldn't that be considered "reading
from a pointer that has already been freed"?

~~~
ustolemyname
That can't happen. The GC won't free the object until nothing references it,
and in your proposed scenario either the channel or receiving goroutine will
have a valid reference.

~~~
brobinson
Thanks for the explanation. I didn't realize Go's GC also worked for
pointers/references.

~~~
brobinson
Let me qualify that: work for them _across goroutines_

------
anentropic
Docker

------
jwatte
As a slightly improved perl that really didn't change anything about
languages.

