<aside> ☝
NOTE: By service I mean any long-living object, it could be just a module/server/etc.
</aside>
To control a service, use this approach:
type Service struct {
quit chan struct{}
wg sync.WaitGroup
}
// Run should be a blocking call.
// To stop it, call Stop.
func (s *Service) Run() {
ctx, cancel := context.WithCancel(context.Background())
s.wg.Add(1)
go func() {
defer s.wg.Done()
s.worker.Start()
}()
defer s.worker.Stop()
s.wg.Wait()
}
func (s *Service) Stop() {
s.quit <- struct{}{}
}
func (s *Service) Work(ctx context.Context) {
ctx, cancel := context.WithCancel(ctx)
go func() {
case <-s.quit:
cancel()
}()
work(ctx)
}
By forcing Run
to be a blocking call, we ensure: