func (em *managerImpl) Start() { //开启子线程 go em.eventLoop() } func (em *managerImpl) eventLoop() { for { select { case next := <-em.events: em.Inject(next) case <-em.exit: logger.Debug("eventLoop told to exit") return } } } //传递Event给receiver func (em *managerImpl) Inject(event Event) { if em.receiver != nil { SendEvent(em.receiver, event) } } //调用receiver.PeoceesEvent方法将事件传递给接收者 func SendEvent(receiver Receiver, event Event) { next := event for { // 如果ProcessEvent方法返回值不为空,则作为新的事件,继续处理 next = receiver.ProcessEvent(next) if next == nil { break } } }
func (et *timerImpl) loop() { var eventDestChan chan<- Event //内部缓存通道 var event Event //事件
for { select { case start := <-et.startChan: //计时开始,时间为start.duration,事件为start.event if et.timerChan != nil { if start.hard { logger.Debug("Resetting a running timer") } else { continue } } logger.Debug("Starting timer") et.timerChan = time.After(start.duration) if eventDestChan != nil { logger.Debug("Timer cleared pending event") } event = start.event eventDestChan = nil case <-et.stopChan: //结束计时 if et.timerChan == nil && eventDestChan == nil { logger.Debug("Attempting to stop an unfired idle timer") } et.timerChan = nil logger.Debug("Stopping timer") if eventDestChan != nil { logger.Debug("Timer cleared pending event") } eventDestChan = nil event = nil case <-et.timerChan: //倒计时触发,这里好绕,倒计时触发,仅仅只是将事件传递通道的引用缓存下来 logger.Debug("Event timer fired") et.timerChan = nil eventDestChan = et.manager.Queue() case eventDestChan <- event: //如果事件传递通道不为空,且event也不为空,则将event传递给事件通道中 eventDestChan <- event这一句话就竟然能实现这么多件事! logger.Debug("Timer event delivered") eventDestChan = nil case <-et.exit: //退出 logger.Debug("Halting timer") return } }
代码看到,倒计时触发的时候,并不是立即直接将event送入通道,而是将通道缓存下来,等到下一次select,再执行将事件送入通道的事。在nil通道上发送和接受将永远被阻塞,在select中,如果其通道是nil,它将永远不会被选择。所以,上述eventDestChan如果为nil, case eventDestChan <- event的语句就不会被选择。eventDestChan不为nil时,就能被选择了,select的用法是不是感觉很赞!