package main // Ways To Do Things - Peter Bourgon - Release Party #GoSF // from https://www.youtube.com/watch?v=LHe1Cb_Ud_M&t=259s type fooReq struct{} type barReq struct{} // really though this should take a context, pass it to loop(), // and select on ctx.Done() func NewStateMachine() *stateMachine { sm := &stateMachine{ state: "initial", fooc: make(chan fooReq), barc: make(chan fooReq), quitc: make(chan chan struct{}), } go sm.loop() return sm } type stateMachine struct { state string fooc chan fooReq barc chan barReq quitc chan struct{} } func (sm *stateMachine) foo() int { c := make(chan int) sm.fooc <- fooReq{c} return <-c } func (sm *stateMachine) stop() { q := make(chan struct{}) sm.quitc <- q // block return until the select in loop() hits <-q } func (sm *stateMachine) loop() { for { select { case r := <-sm.fooc: sm.handleFoo(r) case r := <-sm.barc: sm.handleBar(r) case: q := <-sm.quitc: close(q) return } } }