3 ms·
Most of my non trivial goroutines are organized like this: func actor_foo(things) error { set_up_stuff() defer clean_up_stuff() for { sel
by sly010 10y ago
Most of my non trivial goroutines are organized like this:
func actor_foo(things) error {
set_up_stuff()
defer clean_up_stuff()
for {
select {
case msg := <-messages:
switch msg.(type) {
case *Bla:
}
case <- other_messages:
case <- errors:
case <- signals:
return nil
}
}
}
I recognize there is more to the actor model than just message loops, but I found that an explicit for-select-switch results in better overall readability.
- bmurphy1976 10y agoIs signals your "done" channel?
- sly010 10y agoI was just trying to convey an example. I usually "signal" that the parent wants to stop this "actor" for some reason (e.g graceful shutdown). If parent need a "done" channel, it passes it in and "actor" closes it on its way out. Cleanup usually "signals" children and waits for them to be "done". Sometimes "done" is just signalled by the goroutine returning and it is wrapped in parent somehow. But every time I try to formalize it into some "framework" my abstraction fails.
- scarnie 10y agothe only challenge here is that upstream senders will block when your channel(s) are full. This is not inherently bad, but if you have a circular dependency, you can deadlock because queues (channels) are bounded and may fill up. There are solutions to that too, but you have to build that in