這是最後的片段,在另外兩個額外的協程已經被建立以及準備執行之後,準備立馬執行。這代碼是在主協程中,它的目的是確保主協程直到所有的工作完成才終止。 for迭代和jobs一樣多次,在每次迭代都完成從done通道接收(把結果丟掉),來確保每一個迭代都是同步的以及每個job的完成。如果沒有東西能夠接收(因為某個job正在被執行但還沒結束),接收將會堵塞。一旦所有的jobs被完成,從done通道發送和接收的數量將會和迭代的次數相同,for迴圈將會完成。在此刻,主協程將會結束,因此整個程式終止,我們確信所有的處理都完成。 兩個拇指規則通常都適用於通道。第一,我們只需要關閉通道,當我們將檢查它是否過會被關閉(使用for ... range 迴圈,select,或者檢查接收方使用<-操作)。第二,一個通道應該被發送方協程關閉,而不是被接收方協程關閉。不關閉通道是非常明智的,這樣就從不用去檢查通道是否被關閉,通道是非常輕量級的,所以他們是不佔用資源的,比如開啟一個檔案。 在這個例子中,根據我們的拇指規則,jobs通道用for...range來迭代迴圈,所以我們在發送方協程中完成關閉了它。在另一方面,我們不需要擔心是否關閉了done通道,所以沒有聲明取決於他被關閉後。 這個例子展示了一個在Go並發變成普通模式,儘管在這個特別的例子使用並發並不是真的很好。下面模組的例子用了和這個展示相類似的模式,也充分地使用了並發性。 7.2 例子 雖然Go使用了相當少得文法來提供協程和通道(<-,chan,go,select),但這已經足夠在多種方式實現並發。事實上,有很多不同的方法是可行的,在這一章講解每一種變化是不切實際的。所以,我們會關注通常使用在並發變成中的三中模式,通道,多個獨立並發工作(同步與不同步結果),和多個相互依賴的並發工作,然後看看各自使用Go的並發支援來實現的獨特方式。 當中,會在這展樣本子,以及在最後提供足夠的練習去洞悉和練習Go編程,這些以及其他方法都能夠安全地使用在新程式中。 7.2.1 例子:filter 第一個例子被設計展示一個獨特的並發變成模式。程式能夠很容易適應於其他得益於程式的並發性的工作。 那些使用Unix環境的人可能已經發現Go的通道,聯想於Unix管道(除了通道是雙向,而管道是單向的)。這些管道能夠用來建立用來把一個程式的輸出傳遞給另外一個程式,當做另一個程式的輸入,再把輸出返回給第三個程式等等的通道。例如,使用Unix管道命令 find $GOROOT/src -name "*.go" | grep -v test.go,我們可以獲得包含在Go資源樹的所有Go檔案清單(不包括測試檔案)。這個方法的一個亮點是容易擴充。例如,我們能夠增加 |xargs wc -l 來得到並列出每一個檔案所包含的行數(在最後加上總數),增加|sort -n 來根據行數排序(最少到最多)。 |