// SafeWaitGroup must not be copied after first use.
typeSafeWaitGroupstruct{wgsync.WaitGroupmusync.RWMutex// wait indicate whether Wait is called, if true,
// then any Add with positive delta will return error.
waitbool}...
func(p*sharedProcessor)run(stopCh<-chanstruct{}){func(){p.listenersLock.RLock()deferp.listenersLock.RUnlock()for_,listener:=rangep.listeners{p.wg.Start(listener.run)p.wg.Start(listener.pop)}p.listenersStarted=true}()<-stopChp.listenersLock.RLock()deferp.listenersLock.RUnlock()for_,listener:=rangep.listeners{close(listener.addCh)// Tell .pop() to stop. .pop() will tell .run() to stop
}p.wg.Wait()// Wait for all .pop() and .run() to stop
}
接著來看另外一個範例 wg.StartWithChannel ,範例這個 function 裡面在做什麼我們先不深入研究,把焦點放在 Group 的 StartWithChannel function 與 Wait function 就好。
可以看到一開始透過 Run function 離開時第一個觸發的是 close processor Stop Channel。
可以簡單地理解成廣播說下課,要等所有同學把課本收好才可以離開,而老師就站在前面看著大家收拾。就可以把 wg 想像成老師負責監督大家只要有人沒收好東西就不准最下一步,processorStopCh 可以想成學校的廣播,當廣播發號司令同學就要做某某事情。 source code
1
2
3
4
5
6
7
8
9
10
func(s*sharedIndexInformer)Run(stopCh<-chanstruct{}){deferutilruntime.HandleCrash()...varwgwait.Groupdeferwg.Wait()// Wait for Processor to stop
deferclose(processorStopCh)// Tell Processor to stop
wg.StartWithChannel(processorStopCh,s.cacheMutationDetector.Run)wg.StartWithChannel(processorStopCh,s.processor.run)...}
小結
簡單來說 package wait 只是對 go startand librart 進行簡單的封裝,帶來的效益就是讓大多數的開發者可以沿用這這個封裝好的 package ,因為要達到某一個功能實作的方式有很多種,有了適當的封裝能讓開發風格更統一。文章中若有出現錯誤的見解希望各位在觀看文章的大大們可以指出哪裡有問題,讓我學習改進,謝謝。