[1] https://blog.golang.org/pipelines
It is a very long doc, but that also shows that concurrency has so many patterns one might like.
My own pattern is typically
1. Decide level of parallelism ahead of time and start workers (that many `go X()` invocations 2. Setup sync.Waitgroup for the same count 3. Create two channels, one for each direction. 4. Job itself needs some sort of struct to hold details
Most of my jobs don't support mid-work cancelation, so I don't bother with anything else.
It also uses context (useful for long running, concurrent jobs) and handles mid-work cancellation
Another example of this is how HTTP middlewares chain together, see for example all the middlewares in https://github.com/gorilla/handlers. All of these exhibit one particular quality of idiomatic Go code: a preference for composition over inheritance.
Another quality of idiomatic Go code is that concurrent algorithms prefer channels over locking mechanisms (unless the performance penalty of using channels is too severe). I don't have immediate examples coming to mind on this one though, since the use of channels and mutexes tends to be quite intertwined with the algorithm in question.
> Registry: Keep track of all subclasses of a given class
Go does not have classes.