An Alternative Approach
… continued from the previous post.
Do Not Communicate by Sharing Memory; Instead, Share Memory by Communicating1
This approach can be taken too far. […] But as a high-level approach, using channels to control access makes it easier to write clear, correct programs.1
Let’s just for comparison reformulate the scheme in the last post with shared variables and a sync.WaitGroup
:
|
|
Here we replace the error channel with a function storing the first error and canceling the context. This works fine:
> go run fillmore-labs.com/blog/structured/cmd/structured2
task1 <nil>
task2 failed
task3 context canceled
Got "failed" error in 501ms
But it is a lot of boilerplate.
Refactor and Separate Concerns
We can easily extract the orchestration part:
|
|
Making our function only:
|
|
This separates processing and orchestration, which is nice and makes our code much more readable and improves testability.
Summary
Separating orchestration from the processing code, we can reach simplified structured concurrency with improved readability while eliminating some sources of resource leaks.
… continued in the next post.
Effective Go — 2009 — <golang.org/doc/effective_go.html#sharing> ↩︎ ↩︎