github.com/nofeaturesonlybugs/routines (go): Package routines provides enhanced goroutine synchronization.  The following packages act as dependencies:  I wrote this package to facilitate a sane interface for types that act as long-lived services, consumers, or providers - henceforth referred to as services - within my Go programs.  I consider the following a sane interface:  Furthermore a sane service is goroutine safe; Start() and Stop() can be called any number of times from any number of goroutines.  As noted below consecuitive calls to Start() should return an error.  Start should have the following properties:  Stop should have the following properties:  Due to the properties of Start() and Stop() a service's invocation, error handling, and clean up will be:  The client code invoking the service is incredibly easy to read, follow, maintain, and update.  The deferred Stop() will not return until the service is entirely done, which ensures a clean shutdown of the program.  Any code following the above snippet can be assured the service is running and operational, which eliminates race conditions during program start up.  Furthermore the client code is void of complexity; it is not directly handling the multiple primitives involved for ensuring the defined behavior.  To achieve the above requirements with the built-in concurrency primitives every service needs to manage a wait group, one or more synchronization channels, and possibly a context - or some combination of the three.  The code implementing a service can quickly become cluttered with the code that manages its concurrency patterns, thus reducing readability and increasing complexity.  Reducing readability and increasing complexity have the combined effect of making the service difficult to maintain and difficult to enhance.  The Routines type exported by this package separates the implementation of a service from the management of its concurrency - at least in regards to implementing correct Start() and Stop() methods as described above.  The following is a faily bare implementation of a sane service using only the Routines interface; the next section further simplifies this implementation with the Service interface.  The bare minimum struct definition:  Only two properties are required as part of the structure definition.  A sample Start() implementation:  A sample Stop() implementation:  Both Start() and Stop() contain boiler plate and can be simplified further by introducing a new interface:  First let's make our service's Start() method private and remove some of the boiler plate:  Here is the same method with the boilerplate removed; it is no longer concerned with its concurrency management and only concerned with implementing the service:  The above start method is increadibly lean and deals only with the implementation details of the service - there is no more concurrency management for Start() and Stop().  Next we will eliminate the Stop() method entirely; it's only purpose is to call Stop(), Wait(), and set the child routines object to nil.  This will all be handled by our Service interface.  If you need to clean up any resources as part of stopping the service then the cleanest method is to do that after the `done` label in one of the service's goroutine methods created in start().  Embed our Service interface into our service type:  Finally create a constructor function that sets the embedded Service correctly:  The syntax required to set the embedded property is a little screwy; however it's a tradeoff worth making for consistently designed and implemented consumers, providers, or services within a larger program.
Keywords: concurrency|concurrent-programming|context|go|golang|goroutine|goroutines|multiprocessing|multithreading|waitgroup