I program in Go a lot professionally. I use channels a decent amount of the time, but often drop down to using mutexes or atomics. But I generally prefer channels to mutexes and atomics; generally I reach for those alternatives only due to performance concerns.
One thing that struck me about your comment is referring to actors as a “higher level structure” compared to channels. Comparing Go channels with the actor model is more a matter of apples and oranges than one being more high level than the other. Go is built on the Communicating Sequential Processes (CSP) model: https://en.m.wikipedia.org/wiki/Communicating_sequential_pro... . See the comparison to the actor model in that article if you are curious. The essential idea to CSP is that you have independent processes that only communicate with each other via these channels. This is in comparison to the actor mode where each process has its own dedicated “mailbox” that it can receive from (but can send messages to any other actor it wants). I think that wiki does a better job of outlining the differences than I can in a comment, but essentially these are two similar but subtly different ways to model parallelism.
Personally, I find the CSP model a bit more intuitive than the actor model (though admittedly I have not worked with the actor model as extensively). For the basic idea of “make a process that receives input data, processes it, and submits output data somewhere else” CSP and the actor model are more or less identical. But for more complex use cases, like a process that can receive multiple kinds of messages from different places, or having multiple processes all handling the same stream of incoming data (aka load balancing) I find the CSP model more intuitive. This might be personal bias though. In particular I’ve never seen an actor model with static types and how that would handle different types of messages coming into the mailbox.
Short answer: channels for concurrent programming is definitely a good tool.
Personally, I find the CSP model a bit more intuitive than the actor model (though admittedly I have not worked with the actor model as extensively).
That’s really the question I was trying to ask -- is the CSP style suitably intuitive for general-purpose use? I personally find other primitives easier to use, but that could well just be my bias.
(I’ve done some academic work around process calculi, a long time ago now, and I always found the CSP style much more awkward than CCS / π-calculus.)
I’ve never seen an actor model with static types and how that would handle different types of messages coming into the mailbox.
I think it fits really well in an OO approach, where your messages just become method calls on the actor object -- I believe Swift does that.
That transformation of a method call into a message struct is a kind of defunctionalization, which is a really useful technique (in e.g. Redux) but usually involves a ton of boilerplate. Having a core language primitive that gives you defunctionalization and concurrency, now that’s interesting. I feel like that’s something I would end up building by hand on top of channels (I haven’t done that in Go, but I have for web workers).
> I think it fits really well in an OO approach, where your messages just become method calls on the actor object -- I believe Swift does that.
That’s definitely true. Here’s what I think of as a motivating example: consider a process that takes input data in an input channel, provides some sort of enrichment, and writes the result to an output channel. Simple, right? Now imagine that enrichment requires some sort of configuration data. And that’s mostly static, but there are regular updates to that configuration that are provided by some sort of side channel. In the CSP model, that’s fine: have the process read from two channels, one with input data and the other with updated configuration data. In the Actor model, you have to read from your mailbox, check if this is an input message or a configuration update, and act accordingly. There’s no sort of OO approach that makes that switch statement feel “natural.” I feel that there’s no point into trying to shoehorn both that input data and configuration updates into the same message queue. Any attempt to do so in a clean way is basically just putting arbitrary functions onto a queue.
That said, I recognize that, beyond certain edge cases, the two models are logically equivalent.
> In particular I’ve never seen an actor model with static types and how that would handle different types of messages coming into the mailbox.
This is what sum types give you, or dynamic handler registration if you need to support runtime-configurable message types (perhaps plugins or something).
One thing that struck me about your comment is referring to actors as a “higher level structure” compared to channels. Comparing Go channels with the actor model is more a matter of apples and oranges than one being more high level than the other. Go is built on the Communicating Sequential Processes (CSP) model: https://en.m.wikipedia.org/wiki/Communicating_sequential_pro... . See the comparison to the actor model in that article if you are curious. The essential idea to CSP is that you have independent processes that only communicate with each other via these channels. This is in comparison to the actor mode where each process has its own dedicated “mailbox” that it can receive from (but can send messages to any other actor it wants). I think that wiki does a better job of outlining the differences than I can in a comment, but essentially these are two similar but subtly different ways to model parallelism.
Personally, I find the CSP model a bit more intuitive than the actor model (though admittedly I have not worked with the actor model as extensively). For the basic idea of “make a process that receives input data, processes it, and submits output data somewhere else” CSP and the actor model are more or less identical. But for more complex use cases, like a process that can receive multiple kinds of messages from different places, or having multiple processes all handling the same stream of incoming data (aka load balancing) I find the CSP model more intuitive. This might be personal bias though. In particular I’ve never seen an actor model with static types and how that would handle different types of messages coming into the mailbox.
Short answer: channels for concurrent programming is definitely a good tool.