Comment by bwfan123
21 hours ago
> Concurrency is tricky
The go language and its runtime is the only system I know that is able to handle concurrency with multicore cpus seamlessly within the language, using the CSP-like (goroutine/channel) formalism which is easy to reason with.
Python is a mess with the gil and async libraries that are hard to reason with. C,C++,Java etc need external libraries to implement threading which cant be reasoned with in the context of the language itself.
So, go is a perfect fit for the http server (or service) usecase and in my experience there is no parallel.
> So, go is a perfect fit for the http server (or service) usecase and in my experience there is no parallel.
Elixir handling 2 million websocket connections on a single machine back in 2015 would like to have a word.[1] This is largely thanks to the Erlang runtime it sits atop.
Having written some tricky Go (I implemented Raft for a class) and a lot of Elixir (professional development), it is my experience that Go's concurrency model works for a few cases but largely sucks in others and is way easier to write footguns in Go than it ought to be.
[1]: https://phoenixframework.org/blog/the-road-to-2-million-webs...
I worked in both Elixir and Go. I still think Elixir is best for concurrency.
I recently realized that there is no easy way to "bubble up a goroutine error", and I wrote some code to make sure that was possible, and that's when I realize, as usual, that I'm rewriting part of the OTP library.
The whole supervisor mechanism is so valuable for concurrency.
> Java etc need external libraries to implement threading
Java does not need external libraries to implement threading, it's baked into the language and its standard libraries.
> Java etc need external libraries to implement threading which cant be reasoned with in the context of the language itself.
What do you mean by this for Java? The library is the runtime that ships with Java, and while they're OS threads under the hood, the abstraction isn't all that leaky, and it doesn't feel like they're actually outside the JVM.
Working with them can be a bit clunky, though.
Also, Java is one of the only languages with actually decent concurrent data structures right out of the box.
I think parent means they're (mostly) not supported via keywords. But you can use Kotlin and get that.
With all due respect, there are many languages in popular use that can do this, in many cases better than golang.
I believe it’s the only system you know. But it’s far from the only one.
> there are many languages in popular use that can do this, in many cases better than golang
I'd love to see a list of these, with any references you can provide.
Erlang, Elixir, Ada, plenty of others. Erlang and Ada predate Go by several decades, too.
You wanted sources, here's the chapter on tasks and synchronization in the Ada LRM: http://www.ada-auth.org/standards/22rm/html/RM-9.html
For Erlang and Elixir, concurrent programming is pretty much their thing so grab any book or tutorial on them and you'll be introduced to how they handle it.
Haskell would be one of them. It features transactional memory, which frees the programmer from having to think about explicitly locking.
Please elaborate or give some examples to back your claim?
There's not that many. C/C++ and Rust all map to OS threads and don't have CSP type concurrency built in.
In Go's category, there's Java, Haskell, OCaml, Julia, Nim, Crystal, Pony...
Dynamic languages are more likely to have green threads but aren't Go replacements.
> There's not that many.
You list three that don't, and then you go on to list seven languages that do.
Yes, not many languages support concurrency like Go does...
3 replies →
Erlang (or Elixir) are absolutely Go replacements for the types of software where CSP is likely important.
Source: spent the last few weeks at work replacing a Go program with an Elixir one instead.
I'd use Go again (without question) but it is not a panacea. It should be the default choice for CLI utilities and many servers, but the notion that it is the only usable language with something approximating CSP is idiotic.
Unless we consider JDK as external library. Speaking of library, Java's concurrency containers are truly powerful yet can be safely used by so many engineers. I don't think Go's ecosystem is even close.
> using the CSP-like (goroutine/channel) formalism which is easy to reason with
I thought it was a seldom mentioned fact in Go that CSP systems are impossible to reason about outside of toy projects so everyone uses mutexes and such for systemic coordination.
I'm not sure I've even seen channels in a production application used for anything more than stopping a goroutine, collecting workgroup results, or something equally localized.
There's also atomic operations (sync/atomic) and higher-level abstractions built on atomics and/or mutexes (sempahores, sync.Once, sync.WaitGroup/errgroup.Group, etc.). I've used these and seen them used by others.
But yeah, the CSP model is mostly dead. I think the language authors' insistence that goroutines should not be addressable or even preemptible from user code makes this inevitable.
Practical Go concurrency owes more to its green threads and colorless functions than its channels.
> colorless
Functions are colored: those taking context.Context and those who don't.
But I agree, this is very faint coloring compared to async implementations. One is free to context.Background() liberally.
Go is such a good fit for multi-core, especially that it is not even memory safe under data races..
It is rare to encounter this in practice, and it does get picked up by the race detector (which you have to consciously enable). But the language designers chose not to address it, so I think it's a valid criticism. [1]
Once you know about it, though, it's easy to avoid. I do think, especially given that the CSP features of Go are downplayed nowadays, this should be addressed more prominently in the docs, with the more realistic solutions presented (atomics, mutexes).
It could also potentially be addressed using 128-bit atomics, at least for strings and interfaces (whereas slices are too big, taking up 3 words). The idea of adding general 128-bit atomic support is on their radar [2] and there already exists a package for it [3], but I don't think strings or interfaces meet the alignment requirements.
[1]: https://research.swtch.com/gorace
[2]: https://github.com/golang/go/issues/61236
[3]: https://pkg.go.dev/github.com/CAFxX/atomic128
Erlang.
Swift? JavaScript?
JavaScript? How, web workers? JavaScript is M:1 threaded. You can’t use multiple cores without what basically amounts to user space ipc
Not to dispute too strongly (since I haven't used this functionality myself), but Node.js does have support for true multithreading since v12: https://nodejs.org/dist/latest/docs/api/worker_threads.html. I'm not sure what you mean by "M:1 threaded" but I'm legitimately curious to understand more here, if you're willing to give more details.
There are also runtimes like e.g. Hermes (used primarily by React Native), there's support for separating operations between the graphics thread and other threads.
All that being said, I won't dispute OP's point about "handling concurrency [...] within the language"- multithreading and concurrency are baked into the Golang language in a more fundamental way than Javascript. But it's certainly worth pointing out that at least several of the major runtimes are capable of multithreading, out of the box.
5 replies →
Erlang?
This is a diabolical take