N chans 1 chan + Clean separation of concerns - Logic separate from methods - More types and fields; verbose - Mixing mechanics and logic
· Relatively few API methods · Request/response pattern - Maybe not totally obvious + Colocate method and logic + Fewer types and fields + Mechanics and logic separate
go loop Run + Obvious (?) + Self-contained component + Lifecycle encapsulation - Tricky to get determinism - Tricky to make re-entrant
· Simpler components · When easy > correct - More work for caller - More state to track + Less scaffolding in component + Straightforward determinism + Much easier to test!
go sm.Run(ctx) // cancel() go http.Serve(ln, api) // ln.Close() go cronJobs(cancelCron, sm) // close(cancelCron) go signalCatcher(cancelSig) // close(cancelSig)
go sm.Run(ctx) // cancel() go http.Serve(ln, api) // ln.Close() go cronJobs(cancelCron, sm) // close(cancelCron) go signalCatcher(cancelSig) // close(cancelSig)
Use a group var g group.Group { ctx, cancel := context.WithCancel(context.Background()) g.Add(func() error { return sm.Run(ctx) }, func(error) { cancel() }) }