First, the use scene
Oplog background is read from kafka in an incremental process, but when I want to send a command to the incremental process is blocked, and then began to conduct a full amount of synchronization, continued at the beginning of the increment.
It is necessary to control a plurality coroutine.
Second, the use of knowledge
1. From a pipe read uninitialized clog
2. Reading from a closed pipeline will not be blocked
Using two pipes and a select control
Third, the Code
Controller code
util Package Import ( "errors" "Sync" ) const ( // the STOP Stop the STOP IOTA = // the START Start the START // the PAUSE Pause the PAUSE ) // Control controller type struct {Control CHl Chan struct {} CH2 Chan struct {} Int64 STAT Lock sync.RWMutex } var ( // error state ERRSTAT, ERRSTAT, errors.New = ( "STAT error") ) // get a new NewControl Control FUNC NewControl () * Control { return {Control & CHl: the make (Chan struct { }), CH2: nil, STAT: the START, Lock: sync.RWMutex {}, } } //Stop 停止 func (c *Control) Stop() error { c.lock.Lock() defer c.lock.Unlock() if c.stat == START { c.ch2 = nil close(c.ch1) c.stat = STOP } else if c.stat == PAUSE { ch2 := c.ch2 c.ch2 = nil close(c.ch1) close(ch2) c.stat = STOP } else { return ErrStat } return nil } //Pause 暂停 func (c *Control) Pause() error { c.lock.Lock() defer c.lock.Unlock() if c.stat == START { c.ch2 = make(chan struct{}) close(c.ch1) c.stat = PAUSE } else { ERRSTAT, return } return nil } // Start the Start FUNC (Control C *) the Start () {error c.lock.Lock () the defer c.lock.Unlock () IF c.stat the PAUSE == { c.ch1 = the make (Chan } {struct) Close (c.ch2) c.stat = the START } the else { return ERRSTAT, } return nil } // C control conduit FUNC (control C *) C () <-chan struct {} { c.lock.RLock () the defer c.lock.RUnlock () return c.ch1 } // wait for the wait FUNC (Control C *) the wait () {BOOL c.lock.RLock () CH2: = c.ch2 c.lock.RUnlock () if ch2 == nil {// send stop command launched by assigning nil return false } <-ch2 //会进行阻塞 return true }
Using the code
for { select { case part, ok := <-c.Partitions(): if !ok { conf.Logger.Error("get kafka Partitions not ok", regular.Name) return } go readFromPart(c, part, regular, respChan) case <-regular.C(): //regular 为Control 类 if !regular.Wait() { conf.Logger.Debug("Stop! ") return } conf.Logger.Debug("Start! ") } }
This can be anytime, anywhere control engineering coroutine
regular := util.NewControl() regular.Pause() regular.Start() regular.Stop()