Do people actually use mutices in Go? Coming from Erlang it is such blasphemy. Use The Channel, Luke.
Yes! Channels are slow. If you’re writing high-performance Go you won’t use them, you’ll use mutexes (or better yet, lock-free). If you look at the standard library, you’ll notice channels are rarely used. Their “API” also has a lot of annoyances.
Channels are not great for workload throughput. They are better suited as a mechanism for signaling and timing related code. In general, channels are a coordination pattern. This is where they are really useful and performance is a non-issue. In that regard, I still see them as a nice tool for communication when used for the right job. Buffered channels, on the other hand, are just a less interesting blocking queue.
This is tricky. :) People come to Go from writing database-backed Web apps in Ruby or Python, and from writing highly tuned CPU-bound C and C++ code. “Slow” can mean pretty different things in those worlds.
A toy program got about 2m unbuffered sends/s. If you’re anywhere near millions of sends/s, there’s a good chance you want to bundle up work to send (one example, another) or use something other than a channel. If not, you can do whatever’s easiest.
As a separate thing, I think folks starting out are sometimes tempted to, in effect, use a channel to build a WaitGroup, mutex, etc., instead of picking the right tool from sync. I was guilty of that in my first Go code. Lots of new Go users could probably use exposure to some channel-y and some non-channel-y examples to see where different approaches can make sense.
Wha?? How can channels be slow? It is like making an OO language where objects are too expensive to use.
No , but it’s there.
Does Go give any guarantees around two goroutines modifying the same data?
No, although if you generally follow the pattern “ownership is passed through channels” (by not holding on to references after putting an item into a channel) it works out ok and you have few or zero places with hand-writen mutexes. goroutines + channels are fast enough that I’ve rarely needed an explicit mutex. The designs that come out of that often look like pipelines or trees that match the program’s actual data flow so it’s pretty nice. I look at the mutexes as being similar to unsafe, the trap door is important but rarely used.
Go’s memory model describes all the ways of enforcing the order of concurrent operations.
As I understand it, as long as the goroutines pass the data to each other with channels its safe.
(But my Go is limited; someone correct me if I’m wrong)
None, but it can be very useful to share read-only memory between multiple goroutines. Plus you can use atomic operations to share mutable state efficiently.