| Go allows you to share memory between goroutines (i.e. concurrent code). It doesn't force you to do so. In fact, the Go team explicitly tells you not to do that: "do not communicate by sharing memory; instead, share memory by communicating." (http://blog.golang.org/2010/07/share-memory-by-communicating...) i.e. they tell you to use the Erlang model. But as everything, there are trade-offs. Even Go team uses shared memory protected by locks in some cases (see Go standard library) because it's faster or easier that way. Every good idea (sharing memory between threads is dangerous and therefore should be avoided) taken to extreme becomes cargo cult programming. Yes, it is dangerous, but at the same time there are plenty of successful projects that do it because there are programmers that can contain that complexity despite the somewhat popular view that this approach dooms you to failure. |
An Erlang process has its own heap, so when it blows up, its state just goes away, leaving your remaining program's state untouched. With Go, there is no way to recover sanely; even if your goroutines are designed to copy memory, Go itself has a single heap.
Now, this is a very odd design decision for a language that claims it's designed for reliability. Perhaps Go's authors thinks it's better just for the entire program to die if a single goroutine falls over; well, that's one way, but it's a crude one. Erlang's design is simply better.
I wonder if Go can ever adopt per-goroutine heaps, or whether it's too late at this stage. I was happy to see that Rust has chosen to follow Erlang's design by having per-task heaps, even if all the pointer mechanics (three times of pointers, ownership transfer, reference lifecycles and so forth) result in some fairly intrusive and gnarly syntax.