一個有趣的求解質(zhì)數(shù)的golang代碼

看到一個golang寫的求質(zhì)數(shù)的程序益兄,第一眼看上去很難理解锻梳,理解了之后又覺得很有趣,特此分析一下净捅。

代碼

package main

import "fmt"

// Send the sequence 2, 3, 4, ... to channel 'ch'.
func generate(ch chan int) {
    for i := 2; ; i++ {
        ch <- i // Send 'i' to channel 'ch'.
    }
}

// Copy the values from channel 'in' to channel 'out',
// removing those divisible by 'prime'.
func filter(in, out chan int, prime int) {
    for {
        i := <-in // Receive value of new variable 'i' from 'in'.
        if i%prime != 0 {
            out <- i // Send 'i' to channel 'out'.
        }
    }
}

// The prime sieve: Daisy-chain filter processes together.
func main() {
    ch := make(chan int) // Create a new channel.
    go generate(ch)      // Start generate() as a goroutine.
    for i:=0; i<20; i++{
        prime := <-ch
        fmt.Print(prime, " ")
        ch1 := make(chan int)
        go filter(ch, ch1, prime)
        ch = ch1
    }
}

分析

首先疑枯,求質(zhì)數(shù)(素數(shù))有很多種方法,這個代碼用的方法是:

假設(shè)有一個數(shù)n,已知小于n的所有質(zhì)數(shù)的集合是arr,如果arr中的每個質(zhì)數(shù)都不能夠整除n蛔六,則n就是質(zhì)數(shù)荆永。這是因為任意一個合數(shù)都可以分解成質(zhì)數(shù)的乘積废亭。

例如,

因為 2 是質(zhì)數(shù)具钥,初始化 arr=[2]豆村;

當n=3,3 % 2 != 0, 則 n=3是質(zhì)數(shù), arr=[2,3]骂删;

當n=4掌动,4 % 2 == 0, 不滿足要求,則4不是質(zhì)數(shù)宁玫, arr不變坏匪;

當n=5,,5 % 2 != 0, 5 % 3 != 0, 則 n=5是質(zhì)數(shù)撬统, arr=[2,3,5];

... 依此類推

兩個主要的函數(shù)

  1. generate函數(shù)就是往通道ch中放入n(從2開始)進行篩選适滓。這個ch是沒有緩沖區(qū)的通道。程序一開始恋追,就啟動一個協(xié)程執(zhí)行generate函數(shù)(稱之為generate協(xié)程)凭迹。

  2. filter函數(shù)有三個參數(shù),兩個無緩沖區(qū)的通道苦囱,inout嗅绸,和一個質(zhì)數(shù)prime。首先從in中取出一個數(shù)據(jù)i撕彤,如果i不能夠被prime整除鱼鸠,則說明它有可能是個質(zhì)數(shù),則將其放入out通道中羹铅。

    重點有兩個地方蚀狰,首先filter函數(shù)居然有個for循環(huán)(說明不止使用一次),其次职员,out的數(shù)據(jù)由誰嚷樘!?

主邏輯

   for i:=0; i<20; i++{
       prime := <-ch   // [1]
       fmt.Print(prime, " ")
       ch1 := make(chan int)  // [2]
       go filter(ch, ch1, prime)  // [3]
       ch = ch1   // [4]
   }

首先焊切,代碼[1]從通道ch中取出一個數(shù)2扮授,它必然是質(zhì)數(shù)。代碼[2]新建了一個無緩沖的通道ch1专肪,代碼[3]啟動一個協(xié)程運行fliter函數(shù)(稱之為fliter1協(xié)程)刹勃,其中參數(shù)inchoutch1嚎尤,prime2荔仁,語句[4]是將通道ch賦值為了通道ch1,然后又轉(zhuǎn)到了語句[1],這實質(zhì)上就是從ch1中取數(shù)據(jù)咕晋,也其實就是從fliter1協(xié)程的out通道取數(shù)據(jù)雹拄。

fliter1協(xié)程的in通道會接收到數(shù)字3(由generate協(xié)程放入),經(jīng)過判斷掌呜,將3放入了out通道滓玖。在語句[1]中,從ch也就是out通道中取出3并打印质蕉。

當判斷數(shù)字3時势篡,如圖所示:

輸入3時.png

打印出數(shù)字3之后,又啟動了一個協(xié)程運行fliter函數(shù)模暗,稱之為fliter2協(xié)程禁悠,它的參數(shù)in是通道ch,實際上就是之前的ch1兑宇,也就是fliter1協(xié)程的out通道碍侦!而out通道最后又賦值給了ch。而這時的prime變成了3隶糕。這樣做顯而易見瓷产,因為再次新來一個數(shù)的時候,不僅需要看能不能被2整除(由fliter1協(xié)程判斷)枚驻,還要看能不能被3整除(由fliter2協(xié)程判斷)濒旦。

當判斷數(shù)字4時,由于fliter1協(xié)程判斷不通過再登,所有并沒有放入fliter2協(xié)程尔邓,語句[1]也就不能取出數(shù),就會阻塞锉矢。

當判斷數(shù)字5時梯嗽,傳入fliter1協(xié)程,通過沈撞,再次傳入fliter2協(xié)程慷荔,繼續(xù)判斷通過,從out通道傳出缠俺,實際上就是語句[1]ch通道,所有打印出5贷岸。

當判斷數(shù)字5時壹士,如圖所示:

輸入5時.png

所以,可以推理出偿警,數(shù)字n前面有m個質(zhì)數(shù)躏救,就會產(chǎn)生mfliter協(xié)程,這些協(xié)程串聯(lián)在一起,每個協(xié)程負責判斷能否被某個質(zhì)數(shù)整除盒使,如果不能崩掘,則傳遞個給下一個協(xié)程進行判斷,直至輸出少办。

總結(jié)

  • ch=ch1的時候苞慢,原先的ch并沒有消失,還被之前啟動的fliter協(xié)程保存著英妓。
  • 巧妙使用通道的性質(zhì)挽放,將多個協(xié)程進行串聯(lián)。
  • 最開始我還以為是一個并行的篩選質(zhì)數(shù)的代碼蔓纠,結(jié)果并不是辑畦,其實是串行執(zhí)行。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末腿倚,一起剝皮案震驚了整個濱河市纯出,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌敷燎,老刑警劉巖暂筝,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異懈叹,居然都是意外死亡乖杠,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進店門澄成,熙熙樓的掌柜王于貴愁眉苦臉地迎上來胧洒,“玉大人,你說我怎么就攤上這事墨状∥缆” “怎么了?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵肾砂,是天一觀的道長列赎。 經(jīng)常有香客問我,道長镐确,這世上最難降的妖魔是什么包吝? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮源葫,結(jié)果婚禮上诗越,老公的妹妹穿的比我還像新娘。我一直安慰自己息堂,他們只是感情好嚷狞,可當我...
    茶點故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布块促。 她就那樣靜靜地躺著,像睡著了一般床未。 火紅的嫁衣襯著肌膚如雪竭翠。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天薇搁,我揣著相機與錄音斋扰,去河邊找鬼。 笑死只酥,一個胖子當著我的面吹牛褥实,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播裂允,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼损离,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了绝编?” 一聲冷哼從身側(cè)響起僻澎,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎十饥,沒想到半個月后窟勃,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡逗堵,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年秉氧,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蜒秤。...
    茶點故事閱讀 40,146評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡汁咏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出作媚,到底是詐尸還是另有隱情攘滩,我是刑警寧澤,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布纸泡,位于F島的核電站漂问,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏女揭。R本人自食惡果不足惜蚤假,卻給世界環(huán)境...
    茶點故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望吧兔。 院中可真熱鬧勤哗,春花似錦、人聲如沸掩驱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽欧穴。三九已至民逼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間涮帘,已是汗流浹背拼苍。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留调缨,地道東北人疮鲫。 一個月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像弦叶,于是被迫代替她去往敵國和親俊犯。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,107評論 2 356