Since you mention Haskell, I would like to say that Haskell's concurrency support is more diverse and at least as easy as Go's.
Since you mention Haskell, I would like to say that Haskell's concurrency support is more diverse and at least as easy as Go's.
More diverse is easy, Go is opinionated about its concurrency.
"At least as easy" is a flaming lie. The diversity alone makes it impossible but beyond that:
* when you look for concurrent go you're introduced to 3 constructs (`go`, channels and `select`) and you're off to the race having barely learned the language
* when you look for concurrent haskell you're directed towards the corresponding paper, "tackling the awkward squad" and a world of Async, MVar, ThreadId, STM and various types of Chan, and at that point you still can't write a line of concurrent haskell
Like the_duke I don't enjoy Go, but with respect to dead-easy concurrency the only language that's in the same ballpark is Erlang (and it's similarly boiled down to a complete lack of diversity — though a different model than Go's — and three basic constructs: `spawn`, `receive` and `!`).
I was directed here: http://community.haskell.org/~simonmar/pcph/
And after reading the first few chapters, I'd place go's options under the Rich Hickey quote of simple versus easy. Additionally I sped up a simulated annealing program with the accelerate framework in Haskell by typing "Acc " twice. From 1 000 iterations/minute to about 500 000. I'd call that an easy win. Haskell also allows for more than simply concurrent programming. I always ended up with locks in go and wondering why I was using it over c with an event loop and threads at that point.
Haskell's concurrency disadvantage is the same set of answers to the same question. It intrinsically has a big toolbox to start with, and a bigger one once you get into the libraries that implement further things on top of it (the pipe libraries, for instance), and that intrinsically makes it harder.
So, for instance, yes, you certainly sped up your program very easily, but new users often have a hard time finding their way to the best resources, and if their problem is not a trivially parallelizable algorithm, which it sounds like you had, there can still be some trouble in figuring out which concurrency construct they need.
That said, one downside of STM is that it isn't as efficient as some other schemes especially with high contention, as everything gets serialized through the metadata for tracking transactions. It's an awesome tool, but not a panacea (like with any other technology).
(I'm sure you know this, but others reading the thread may not.)