2017-01-20 70 views
1

我來自一個Node.js背景,其超級容易做一些異步工作,然後做一些更多的工作,在長時間運行的任務完成,我敢肯定它在Go中是一樣的,但我只是沒有我的腦袋裏圍繞着頻道如何工作。我是否在golang中使用了不正確的頻道?

我正在構建一箇舊遊戲的解析器,我玩的是從拍賣數據日誌中分析線路,並將它們解析爲通過套接字io流到網站上的實時饋送。一個文件一次可以發送100行,而我的解析器必須一次一行地分析每行,並從每行中提取元信息(例如項目,項目價格等)。

每條單一行都有for循環針對它運行(假定其中的項目列表已經從正則表達式得到的部分):

itemChannel := make(chan Item) 

for _, itemName := range itemList { 
    item := Item { 
     Name: itemName, 
    } 

    // Long running method which does parsing for the item such as pricing, quantity and makes some http calls (runs 75ms on average) 
    go item.FetchData(itemChannel) 

    // Read from the channel when its done 
    raw := <-itemChannel 
    auction.Items = append(auction.Items, raw) 
    auction.Seller = seller 
} 

auctions = append(auctions, auction) 
fmt.Println("Appended auction: ", auction) 
go c.publishToRelayService(auction) 

現在(從觀察中),它好像raw := <-itemChannel導致循環阻塞,直到夠程完成並通過它的數據返回(這肯定意味着運行,因爲item.FetchData(itemChannel)會做同樣的事情。我怎樣才能從通道讀取數據回來,但儘可能快地跳出循環迭代。行中有15-20項,導致程序在解析下一行之前暫停〜2-3秒。我希望能夠儘快解決和處理下一行,以儘可能快地保持解析器。是否有任何類似Promise in Node的機制,我可以將完成處理程序鏈接到每個完成的item.FetchData()

注意fetchChannel被寫入我的項目類型的內部,當所有提取工作已完成。

+0

你可以放一個可運行的代碼去玩嗎?它會更好地理解這個問題 –

+0

嘿我其實只是通過給我的FetchData方法添加一個回調函數來解決這個問題。因此,總結渠道阻塞,如果是的話,爲什麼我們使用它們?對於分佈在不同系統中的相同程序的IPC,它更多嗎? – Alex

+0

是通道阻塞,除非它被緩衝。 –

回答

2

您可以編寫一個不同的go例程,等待通道中的新數據並處理它。 這樣,生產者和消費者都平行,當生產者與生產消費做必須爲這裏的消費是一種輕過程

可以使用done通道,表明消費者做做

這裏是你可以如何改變代碼

itemChannel := make(chan Item) 
done := make(chan bool) 
//Consumer 
go func(channel chan Item) { 
    for raw := range channel { 
     auction.Items = append(auction.Items, raw) 
     auction.Seller = seller 
     auctions = append(auctions, auction) 
    } 
    done <- true 
}(itemChannel) 

//Producer 
for _, itemName := range itemList { 
    item := Item{ 
     Name: itemName, 
    } 

    // Long running method which does parsing for the item such as pricing, quantity and makes some http calls (runs 75ms on average) 
    go item.FetchData(itemChannel) 

} 

<-done 
fmt.Println("Appended auction: ", auction) 
go c.publishToRelayService(auction) 
+2

有趣的,謝謝你。剛剛實施它,它似乎有伎倆。我想這是「做」的做事方式?看起來超級外星人來自Node背景:P – Alex

+1

一直在那裏兄弟:D –

1

在更廣泛的問題而言,從Node.js的移動去/ CSP通道,則需要通過擱置回調的思維開始。我使用的每個反應/異步範例都是某種形式的回調裝飾,易於使用。但CSP不會試圖這樣。

Go的關鍵之處在於,輕量級goroutine的協作調度發生在與操作系統線程無關的大範圍內(儘管實現者通常盡力通過OS線程儘可能地使用CPU內核技巧在引擎蓋下)。與行動回調沒有真正的比較。

每個goroutines都有自己獨立的生命週期。它可能很短。或者,如果一個goroutine包含一些循環,它可能會存在一段時間,看起來就像一個演員(在演員模型中)。

這是您探索溝通順序過程(CSP)所需的思想。根據數字電子組件模塊思考混合程序也可能是一個有用的類比。門和電線類似於goroutines和頻道。

此外,觸發器可以從幾個門構建 - 同樣,可以由內部通道連接的「較小」的goroutines構成goroutines。如果你做得對,那麼'更大的'goroutine上的外部頻道是其合作者唯一關心的問題(內部頻道是隱藏的)。

這爲設計軟件開闢了新的途徑,也是Rob Pike主張的事情之一:Concurrency is not Parallelism。換個角度思考

一個例子可能是仿真軟件(Conway的大規模生命遊戲)。基於對每個細胞的個體行爲進行建模,我發現了血管中血液流動和凝結的非常引人注目的模擬。該演示包含4000萬個併發實體,這種方法在普通筆記本電腦上運行非常令人印象深刻。

+1

嘿,這是一個超級有趣的閱讀,我絕對想要以這種方式打入寫軟件,我可以看到在並行跨多個系統分發任務時的優勢,這給了我們的潛在力量是巨大的!對於我剛剛通過回調函數的Node和其他語言來說,它對我來說是超級外星人(儘管我明白了Go處理並行性的原因是節點只是併發)。我會給羅布派克斯的文章一個閱讀,再次感謝您的輸入! – Alex

相關問題