No goroutines in init()
init() functions should not spawn goroutines.
See also Avoid init().
If a package has need of a background goroutine,
it must expose an object that is responsible for managing a goroutine's
lifetime.
The object must provide a method (Close, Stop, Shutdown, etc)
that signals the background goroutine to stop, and waits for it to exit.
| Bad | Good |
|---|---|
| ```go func init() { go doWork() } func doWork() { for { // ... } } ``` | ```go type Worker struct{ /* ... */ } func NewWorker(...) *Worker { w := &Worker{ stop: make(chan struct{}), done: make(chan struct{}), // ... } go w.doWork() } func (w *Worker) doWork() { defer close(w.done) for { // ... case <-w.stop: return="" }="" shutdown="" tells="" the="" worker="" to="" stop="" and="" waits="" until="" it="" has="" finished.="" func="" (w="" *worker)="" shutdown()="" {="" close(w.stop)="" <-w.done="" ```="" <="" td="">-w.stop:> |
| Spawns a background goroutine unconditionally when the user exports this package. The user has no control over the goroutine or a means of stopping it. | Spawns the worker only if the user requests it. Provides a means of shutting down the worker so that the user can free up resources used by the worker. Note that you should use `WaitGroup`s if the worker manages multiple goroutines. See [Wait for goroutines to exit](goroutine-exit.md). |