
Some thoughts on Go and Erlang - rubyrescue
http://blog.erlware.org/2014/04/27/some-thoughts-on-go-and-erlang/
======
rdtsc
Very good comparison, stuff that most other blogs don't talk much about --
scheduling, fault isolation, garbage collection strategies. I guess they don't
because other frameworks/languages don't provide that. It usually stays at
syntax level with obligatory mention of generics.

Fault isolation and pauseless garbage collection is something that is very
important in some contexts. Often the need for it becomes apparent the second
time around, after one version of the system has been plagued by large mutable
shared state bugs, or strange, un-predictable response times in a highly
concurrent system.

Do you pay in terms of raw CPU performance by copying messages and keeping
private heaps per lightweight process? Yes you do. There are no magic unicorns
behind the scene. That is the trade-off you get for getting fault isolation
and soft realtime properties. But keep this in mind, one of the biggest
slowdowns a system incurs is when it goes from working to crashing and not
working.

Also, no matter how strong the static compile checking is, your system will
still crash in production. It is usually a hard bug that has been lurking
around not a simple "I thought it was an int but got a string", those are
caught early on. It will probably be something subtle and hard to reproduce.
Can your system tolerate that kind of a crash in a graceful way? Sometimes you
need that.

In the end, it is good for both systems to be around. If you need fault
tolerance, optimization for low latency responses, supervision strategies,
built-in inter-node clustering(node = OS process or instance of running Erlang
BEAM VM) you cannot get that in any other way easily.

Now, one could think of trying to replicate some of the things Erlang
provides. Like say build tools static analysis tools to check if go-routines
end up accessing shared state. Or say, devise a strategy to use channels-based
supervision tree. Heck, if you don't have too many concurrency contexts
(processes, go-routines) you can always fall back on OS process-based
isolation and use IPC (+ ZMQ for example), as a mailbox. But then again Erlang
provides that in one package.

~~~
aaronblohowiak
>Like say build tools static analysis tools to check if go-routines end up
accessing shared state

I believe this is what the go race detector does:
[http://blog.golang.org/race-detector](http://blog.golang.org/race-detector)

~~~
pcwalton
That's not static analysis though.

------
kungfooguru
I've added an update to the top of the post because I didn't make the point
clear enough:

I’m seeing that I did not make the point of this post clear. I am not saying
Go is wrong or should change because it isn’t like Erlang. What I am
attempting to show is the choices Go made that make it not an alternative to
Erlang for backends where availability and low latency for high numbers of
concurrent requests is a requirement. And notice I’m not writing this about a
language like Julia. I have heard Go pitched as an alternative to Erlang for
not only new projects but replacing old. No one would say the same for Julia,
but Go and Node.js are seen by some as friendlier alternatives. And no, Erlang
isn’t the solution for everything! But this is specifically about where Erlang
is appropriate and Go is lacking.

------
jeffdavis
Erlang is a language with a purpose that I can relate to. I develop a cluster
database product, and erlang seems to have an answer for many problems that I
have actually faced.

For instance: cluster global pids. When you send a message to a pid, you don't
have to go through a dance of handling errors and timeouts just because it
might live on another node. If the node goes down, there are several ways to
handle that, including monitor_node() which gives you a message that you can
handle in one place.

I haven't used erlang in production, but I've invested some time to learn
about it because I see that potential value.

I don't really see that from Go. It seems to fall into a "general-purpose"
bucket where it competes with Java, C#, python, ruby, haskell, clojure, scala,
etc. I don't necessarily like all of those languages, and for any given one
you can probably pick out some Go advantages. A lot of people say Go hits a
nice sweet spot for many applications.

But Go just doesn't speak to any problems I actually have. It can't replace
the C/C++ code, because Go has a GC, and the code is C/C++ because it needs to
manage memory[1]. It could replace the python code, perhaps to some benefit,
but there would still be a bunch of awkward communication between processes
and all of the associated error handling mess. And it can't replace Java,
because that's a public API we offer, and lots of people are comfortable with
Java.

Go should have been another cluster language/VM that really could compete with
erlang, in my opinion. To me, Go is just another language.

[1] Rust does seem to have something to offer here.

~~~
jaegerpicker
Just because Go doesn't fit your use case doesn't mean it should be something
else. In most cases Go IS a better choice than C/C++ in a server side case.
For instance let's say you are writing a server for a multiplayer game. Most
of the server's activity is spent on waiting for IO and managing concurrent
socket based connections. There are drawbacks and risks to managing memory in
this type of system and Go's concurrency makes writing this code much easier.
Another great go use case is a rest based web service, a lot of these are
typically written in Java, Ruby, or Python. I love python but go has serious
advantages over all three of those languages in this use case. This is where
go was designed to be used and it's best spot. The glue servers that are most
commonly used for web applications. Go is designed to be simpler, safer, and
easier to write than C/C++, Java, or C# but faster, more modern, and more
fault tolerant than python or ruby. It's not a perfect language by any means
but it does fill a nice sweet spot.

~~~
stcredzero
I'm writing a multiplayer game in Go. The reason I chose it is that it allows
me to control memory layout at a low level. This can be very important for
achieving multicore parallelism. (Also known as optimizing for fewer cache
misses.)

~~~
jeffdavis
That's a good point. There aren't a lot of GC languages that let you control
structure layout. Not a problem I face, but interesting.

~~~
stcredzero
_Not a problem I face, but interesting._

Only a problem you face if you are trying to keep multiple cores busy with low
latency.

~~~
jeffdavis
I think I'm missing your point. Why do you need a GC language for that?

~~~
stcredzero
I was more talking about being able to control memory layout.

------
aufreak3
A meta comment - I'm reading a lot of the "use the right tool for the job and
stop arguing" statement in language/framework/system/machine comparison
threads these days.

I find the "right tool for the job" to be a total conversation stopper. It
stops the bikeshedding type arguments, true, but it also stops potentially
illuminating comparisons. Can we, as a community, agree to stop bringing it up
in comparison arguments?

Imagine a new programming language and system being presented in an article.
It is healthy and useful for the article to say "We designed system X so it is
easier to express Y kind of programs. A, B, C are the complications
encountered when doing the same with systems I, J, K." rather than "We
designed system X to express Y kind of programs. We like it, but if you don't,
use the right tool for your job."

While many of us are polyglots, we do seek to minimize the number of parts
when building a system, so such comparisons are often meaningful at some
level.

~~~
jeffdavis
Agreed.

While we're at it, "the right tool for the job" always struck me as a bad
analogy. Nobody would question a carpenter's tool choices because the only
thing that affects others is the quality of the final result (e.g. how the
building will stand up to stress).

But using a software language, framework, library, database, OS, or other
platform makes it inextricable from the the rest of the product when judging
quality. In some cases, you can make a black box argument like "if a user is
unable to observe any poor qualities, then the product must be of high
quality"; but that only really applies when you are the sole developer and
always will be. For larger projects, there are others involved, and they will
be affected if the building blocks are poor.

Granted, that doesn't mean that all discussions about platforms are
productive, but it means there is some room for illumination and progress.

------
cnbuff410
Is it just me or the author fail to explain all the Go's detrimental design
clearly? Most of the points he listed there are pretty much personal taste
thing and basically what he was saying is "Go has so many problems because Go
is not designed as Erlang".

For example, he said

"But when it comes to complex backends that need to be fault-tolerant Go is as
broken as any other language with shared state."

Why? Why shared state is so bad in Go? Isn't it taken care by Go's channel
anyway?

Also, why Pre-emptive Scheduling is bad? Isn't Error Handling still pretty
much just a matter of personal preference?

Why Introspection makes Erlang so much better? What's the practical key
problem for Go that can not be tackled without instrospection?

And I completely failed to understand the point of "Static Linking".

I'm not trolling. I don't have Erlang experience, and most of the problem the
author pointed out was not bothering me, so I honestly want to see WHY they
are problematic in Go

~~~
riobard
Shared state is bad because it breaks local reasoning. Without enforcing
certain disciplines (i.e. always sharing by passing messages via Go channels)
it's hard, if not impossible, to reason about local behaviors without
considering other parts of the code. Immutable vs shared mutable state is a
design choice. Erlang chose immutability for safety, while Go chose shared
mutable state for practical reasons, but as a remedy Go recommends best
practices to avoid the drawbacks caused by it.

Pre-emptive scheduling is bad because you can have a goroutine running a tight
loop starves other goroutines. To address that problem, you should manually
call runtime.Gosched() to yield control and allow the scheduler to run other
goroutines. Erlang's reduction-based scheduling does not have this problem and
can be very fair.

Goroutine lacking identity is a major design difference from Erlang. In Go,
channels have identity, but goroutines don't. In Erlang, it's the other way
around: processes have identity, and channels are implicit a.l.a mailboxes. In
theory you can simulate one style in the other, but the implication of this
design choice is very proud. I'm a Go fan, but personally I think Erlang's
model is easier to reason about in scale, and it has this nice symmetry with
OS threads/processes (you can kill them easily. Good luck killing a
goroutine).

~~~
cnbuff410
> Erlang chose immutability for safety, while Go chose shared mutable state
> for practical reasons, but as a remedy Go recommends best practices to avoid
> the drawbacks caused by it.

That's my point. I didn't say it clearly before. I understand why shared state
is bad in _general_. I don't understand if channel takes care of most
scenarios why it's still one of biggest problem for Go listed by author.

> Erlang's reduction-based scheduling does not have this problem and can be
> very fair.

What's the key difference between Erlang's reduction based scheduling and
cooperative scheduling?

~~~
derefr
> What's the key difference between Erlang's reduction based scheduling and
> cooperative scheduling?

Cooperative scheduling is like reference-counting: you have to tell the
compiler when it's safe to context-switch. Preemptive scheduling is like
garbage-collection: the runtime decides on its own when it will switch, and
you have to deal with making that safe.

Reduction-based scheduling is a hybrid approach, and is, in this analogy, a
bit like Objective-C's Automatic Reference Counting. Under reduction-based
scheduling, context switches are a _possible_ side-effect of exactly one
operation: function calls/returns. This means that it's very easy to reason
about when context switches _won 't_ happen (so it's not hard to write atomic
code), while not having to worry about _making_ them happen yourself (because,
in a language that defines looping in terms of recursion, all code-paths have
a known-finite sequence of steps before either a function call or a return.)

~~~
cnbuff410
Very clear. The reduction based scheduling certainly looks interesting. Thanks
for your explanation!

------
kator
Interesting read, I have recently been porting a very low latency high scale
project of mine from Nginx/LuaJIT to Go just to learn Go.

I have already right off the bat ran into the concurrency issues even with Go
1.3beta. And the GC locking causes all my connections to drop and thus causes
thrashing.

That said I've coded in many languages in my 30 years of development while
often reverting back to C over and over again as I've needed the lower level
solutions to some big problems. I've enjoyed learning Go and plan to continue
because it just "feels right". It's hard to explain but I can see it useful
for numerous problem sets and I don't have to dive into C++/Java again to get
convenient memory management and hopefully I'll never look pthreads in the
face again.

However, I have really been amazed at the speed of LuaJIT. If you would have
told me the fastest toolset I could use for my low latency high scale project
was an "interpreted language" I would have laughed you out of the room. I did
try Python (Cython) and Java and numerous other tools. But so far LuaJIT has
turned out to be the fastest, not the most elegant to read but coder time -vs-
return on that time is the highest thus far.

I am hopeful that Go will mature in the runtime in ways that will make it
compete with Nginx for it's amazing event driven non-blocking architecture.
With that in mind I think writing many things in Go will be useful and
improvements of the underlying tech will just be magnified by all the code
that now needs just a simple recompile to capture those changes. It's like the
old days of gcc when I found hand coding some ASM was more useful and now a
days it kicks out some amazing code with little need for inlines except in the
most extreme situations. Here's to hoping Go traverses that path faster then
gcc did and we all will have a more enjoyable time solving the problems we
love to solve every day.

~~~
personZ
_I have already right off the bat ran into the concurrency issues even with Go
1.3beta. And the GC locking causes all my connections to drop and thus causes
thrashing._

This sounds somewhat incredible and unlikely to be a result of Go, more likely
to be a facet of a naive implement (we can all break any language). I've built
a number of extremely high capacity/concurrency systems in Go to great
success, as have many other very large organizations, so the notion that it's
just fundamentally immature or broken doesn't fly.

All of the talk about GC in Go is a bit curious, because Go actually makes
very little use of GC -- it very heavily favors the stack, versus many other
platforms (.NET, Java, others) that use the heap for virtually everything, and
turn most everything into an object. The simple fact that Go has a GC doesn't
mean that its GC use is the same as all other languages that use a GC.

------
shmerl
_> his biggest surprise was Go is mostly gaining developers from Python and
Ruby, not C++_

Why is that a surprise? I think it's logical, and Go can be expected to
attract developers who are used to garbage collection (Java, Python, Ruby
etc.). Not so much C++ developers who prefer to have control and choice (i.e.
pay for what you choose, rather than get it handed down forcefully). Rust is a
better candidate for attracting more C++ developers than those from Java,
Python and Ruby background.

~~~
dagw
_Why is that a surprise?_

Because it was never the intention. Pike and Thompson, by their own admission,
hated C++ and set out to write a better language to replace it. Python and
Ruby developers where never on their radar during the whole design phase. It
might be logical and obvious in hindsight, but it certainly came as a surprise
to the creators of the language.

~~~
shmerl
I see. I guess they misjudged features which C++ developers actually valued as
something bad and in need of fixing. I.e. while trying to improve, they
removed something that was actually good (such as replacing RAII with GC). And
on the other hand not fixing real fundamental problems (such as concurrency
safety for example). This probably made the language less attractive as a C++
replacement, but still attractive for those who didn't look to replace C++.

~~~
pjmlp
Not only that.

Many of us that like C++ also do actually like GC systems, but what I
personally don't want to give up is the expressive power of modern languages.

~~~
coldtea
Let's put it this way:

If it wasn't for the Google brand -- with the power to promote Gophercons and
hire full team language devs -- there wouldn't be a chance to see Go rise
above Nimrod, D et al.

What they do have going for them is:

1) A rather complete standard library (because of many paid full time devs
compared to any indie language) 2) An easy familiar syntax 3) A simple (but
far from complete or unique to them) concurrency story with
Channels/Goroutines. 4) Nice tooling (again due to many paid full time devs --
Java and C++ have better, but most languages have worse).

~~~
pjmlp
Yes, I do agree.

------
natural219
The biggest turn-off about Go, for me, is that the community seems to be
incredibly unfriendly to newcomers. He touched on the lack of REPL, but it
goes further than that.

For instance, there is very little in the toolchain about debugging other than
"use GDB". For someone very familiar with the workflow of typing "debugger" in
Javascript code, being able to stop the world at any state, examine variables,
and having a fully-functional REPL to test expressions, Go's way of
"debugging" code is...well. I don't really know how to do it in Go. The
general answer seems to be something along the lines of "think about the code
you wrote and then write it correctly you idiot."

Seriously, this is the canonical debugging advice, from Rob Pike himself:

 _" When something went wrong, I'd reflexively start to dig in to the problem,
examining stack traces, sticking in print statements, invoking a debugger, and
so on. But Ken would just stand and think, ignoring me and the code we'd just
written. After a while I noticed a pattern: Ken would often understand the
problem before I would, and would suddenly announce, "I know what's wrong." He
was usually correct. I realized that Ken was building a mental model of the
code and when something broke it was an error in the model. By thinking about
_how* that problem could happen, he'd intuit where the model was wrong or
where our code must not be satisfying the model."*[1]

[1]
[http://www.informit.com/articles/article.aspx?p=1941206](http://www.informit.com/articles/article.aspx?p=1941206)

~~~
oofabz
Most Go programmers I know use printf debugging, not GDB. It fits with the Go
philosophy of doing everything from the code, minimizing tools and config
files.

This is not because the tools are so bad we are forced to bang rocks together.
It's because writing code is an effective way to diagnose bugs. Even when I'm
in a full-blown IDE with a GUI debugger, I prefer to use printf debugging.

~~~
natural219
I do too, I think this is more efficient when I understand what's going on.

However, let's say I'm given a third party library, and I know essentially
what it does. I want to "see" the properties and methods of the object, I want
to "inspect" values, and I want to "test" expressions, _all at once_. If
you're just using printf, then between each of those steps you need to write a
line of code, recompile, and reach that state in your program again. Like I
said, if you already know essentially what's going on, deep dives like this
become less and less important. However, I just think it's a boneheaded
philosophy for a language / toolchain to just like...I don't know, _assume_
you're good. I'm trying to become good, but I am getting more and more
frustrated with Go every time the default answer to my problem is "be less of
an idiot"

~~~
mercurial
It's not necessarily a matter of being good. Writing efficient code doesn't
mean that you can build a mental model for a reasonably complex projects,
which will naturally accumulate dependencies. If you're lucky, you'll get a
mental model of the component you're working on, and some of the more
problematic dependencies. That's where being able to dive into arbitrary code
during execution becomes crucial. Especially if the problem occurs in a piece
of code you don't have access to at the layer you operate, and hence can't
display the value for easily, or at all.

------
signa11
imho, go, afaik, is designed to cleanly express concurrency primitives in the
context of a single system, and doesn't do 'fault-tolerance' in the erlang
sense of 'you need >1 machine to be fault-tolerant'. with that lens, it is
clear that the _optimal_ way to do concurrency is with shared state, but that
gets exported out via channels and go-routines etc.

also, can someone please explain the issues around 'nil' ? i fail to
appreciate author's concern about those...

~~~
rdtsc
> also, can someone please explain the issues around 'nil' ? i fail to
> appreciate author's concern about those..

The question can be thought of as two parts:

1) Whether nil should be a base value for objects. If something points to type
t, should that be allowed to be nil. It is obvious that it should if coming
from C/C++/Python, not so obvious if coming from Haskell for example.

2) Should the lack of objects, or should error conditions be represented by
nil. Say lack of a an object in a map is indicated by returning nil. Should it
throw an an exception instead? Now, go doesn't have exceptions so it needs
something like this perhaps. Or maybe panic should happen.

To expand on 1). If you are coming from Haskell (or any strong typed language)
the thinking is, you are already paying the price for static checking, strong
types, compilation step etc. It would be nice to have explicit non-nil types.
You can say this function accepts a reference to this object and this cannot
be nil. During compile time the typechecker/compiler will do a more rigorous
analysis based on that, and barf out an error then instead of during
production.

Like in Haskell you can explicitly say something may be nil (Nothing):

    
    
           data Maybe a = Nothing | Just a
    
    

I don't personally lean one way or another here. I just don't have a strong
opinion either way. I understand the trade-off. But this is how I interpret
what the author means by his issue with 'nil'. Hopefully this helps.

~~~
demallien
For 1), modern C++ style generally frowns upon NULL pointers, preferring to
use references, which are guaranteed to be non-NULL.

~~~
dbaupp
There is no such guarantee, a NULL reference can be created although it does
require a little more effort than creating a null pointer.

However, null is just a special case of "invalid" pointer (e.g. point to freed
memory), and it's very easy to create an invalid reference, e.g. take a
reference into a vector and then push a pile more elements onto it, causing
the vector to reallocate and move in memory, invalidating the reference.

~~~
lomnakkus
You're talking about undefined behavior. There's no such thing as a null
reference according to the C++ language specification.

~~~
dbaupp
So? It's still possible to create one. (There's no such thing as dereferencing
an invalid pointer according to the standard, but that still happens.)

~~~
lomnakkus
If it takes undefined behavior to create a "null reference" then by definition
it's not possible to create one and still have a well-defined program. That
is, you have bigger problems than "null references" to worry about.

------
callmeed
Great article.

I'm curious how people are deploying Go apps in production. Is it nginx+some
app server?

(In other words what's to Go equivalent of nginx+unicorn or apache+passenger
in the RoR world?)

~~~
jamra
I use nginx + upstart to keep my golang process up and running. When I asked
about it on the golang irc channel, people said that they just use golang
without a reverse proxy.

I personally like the ssl termination that nginx offers. I believe that nginx
is a better way to load balance and I like not having to run my code as root,
which using a reverse proxy provides you.

~~~
justincormack
You can use capabilities to allow binding to port 80 without being root.

~~~
vertex-four
Another alternative is authbind[0], which doesn't have the same drawbacks
(i.e. you can use it with scripts, and still set LD_LIBRARY_PATH).

[0]
[http://en.wikipedia.org/wiki/Authbind](http://en.wikipedia.org/wiki/Authbind)

------
kkowalczyk
I write it fully acknowledging that programming language flamewars are
pointless, but this article just shows that you don't even have to try hard to
create a biased comparison.

Here's the essential difference between Go and Erlang: Go gets most of the
things right, Erlang gets way too much wrong.

So what does Go gets right but Erlang doesn't:

* Go is fast. Erlang isn't

* Go has a non-surprising, mainstream syntax. You can pick it up in hours. Erlang - not so much.

* Go has a great, consistent, modern, bug-free standard library. Erlang - not so much.

* Go is good at strings. Erlang - not so much.

* Go has the obvious data structures: structs and hash tables. Erlang - no.

* Go is a general purpose language. Erlang was designed for a specific notion of fault tolerance - one that isn't actually needed or useful for 90% of the software but every program has to pay the costs

* Go has shared memory. Yes, that's a feature. It allows things to go fast. Purity of not sharing state between threads sounds good in theory until you need concurrency and get bitten by the cost of awkwardness of having to copy values between concurrent processes

So sure, if you ignore all the major faults of Erlang
([http://damienkatz.net/2008/03/what_sucks_abou.html](http://damienkatz.net/2008/03/what_sucks_abou.html),
[http://www.unlimitednovelty.com/2011/07/trouble-with-
erlang-...](http://www.unlimitednovelty.com/2011/07/trouble-with-erlang-or-
erlang-is-ghetto.html), [http://ferd.ca/an-open-letter-to-the-erlang-beginner-
or-onlo...](http://ferd.ca/an-open-letter-to-the-erlang-beginner-or-
onlooker.html), [http://sacharya.com/tag/erlang-
sucks/](http://sacharya.com/tag/erlang-sucks/)) it compares very favorably to
Go.

You just have to overlook ugly syntax, lack of string type, lack of structs,
lack of hash tables, slow execution time. Other than those fundamental things,
Erlang is great.

~~~
derefr
Note that the people who espouse Erlang are espousing the Erlang VM (mainly
because it doesn't have a name besides "the Erlang VM".) Nobody likes Erlang's
syntax. Nobody likes Java on the JVM either, but Clojure's pretty great. Use
Elixir, and you get pretty syntax, and also "string support" and "a consistent
stdlib" for free.

And, since other people have already rebutted your statements about structs
and hashes, I'll ignore that. †

On needing speed: for IO-bound operations (concurrent ones especially), Erlang
_is_ faster than Go. For CPU-bound operations, Erlang knows it can't beat
native code--so, instead of trying to run at native-code speeds itself, Erlang
just provides facilities for presenting natively-compiled code-modules as
Erlang functions (NIFs), or for presenting native processes as Erlang
processes (port drivers, C nodes.) If you run the Erlang VM on a machine with
good IO performance, and get it to spawn the CPU-bound
functions/processes/C-nodes on a separate machine with good CPU performance,
you get the best of both worlds.

And finally, on "every program having to pay the costs": is someone forcing
you to use Erlang to create something other than fault-tolerant systems? Learn
Erlang. Learn Go. Learn a bunch of other programming languages, too. Use the
right tool for the job. The article is the rebuttal to people who claim that
Go replaces Erlang in Erlang's niche, not a suggestion to use Erlang outside
of its niche.

\---

† For a bonus, though, since nobody seems to have brought this point up:
Erlang has always had mutable hash tables, even before R17's maps. Each
process has exactly one--the "process dictionary." It's discouraged to use
them in regular code, because, by sticking things in the process dictionary,
you're basically creating the moral equivalent of thread-local global
variables. However, if you dedicate a gen_server process to just manipulating
its own process dictionary in response to messages, you get a "hash table
server" in exactly the same way ETS tables are a "binary tree server."

~~~
ithkuil
do you think that BEAM is just the name of the current implementation of the
Erlang virtual machine?

can somebody reimplement a BEAM in the same way you can implement another JVM?

~~~
Jtsummers
strmpnk beat me by 7 minutes, here's a link to the Erjang project:
[https://github.com/trifork/erjang](https://github.com/trifork/erjang)

It's not really "BEAM on the JVM", it's actually a translator of BEAM compiled
code to JVM bytecode. But the concept is similar, the target for Erlang is
important, but so far a variety of things have been used. JAM was the original
VM, later BEAM, later BEAM with HiPE. See [1] for some more information. There
was also, apparently, an Erlang-to-Scheme translator. It'd be interesting
(does this exist yet?) to see someone implement Erlang semantics in Racket.

[1]
[http://www.erlang.org/faq/implementations.html](http://www.erlang.org/faq/implementations.html)

~~~
strmpnk
While it's true that Erjang translates BEAM code, BEAM itself also does this
to yet another more modern internal code (. I'd still consider both BEAM
implementations.

------
JulianMorrison
You can "link" goroutines in Go by using

    
    
      defer func(){
        if recover() != nil {
          // tell my parent I died
        }
      }()
    

and, Go relies on channels, not goroutines, having identity.

------
ch4s3
Pretty interesting read. I keep wanting to come back to Go. Maybe this summer.

------
zimbatm
Not directly related but I'm wondering when or if it's even prossible to
implement OTP on the system level. OTP is basically a process manager with
linked dependencies ? I know unix processes aren't as lightweight but it would
still be useful I think. It's the right level of granularity for languages who
have shared mutable state internally.

~~~
erichocean
From a particular perspective, that's what Docker is trying to do (or at
least, is providing infrastructure to build something like an "OTP for Docker"
with).

