第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

立即退出所有遞歸生成的 goroutine

立即退出所有遞歸生成的 goroutine

Go
胡子哥哥 2023-06-19 15:32:30
我有一個函數(shù)可以遞歸地生成 goroutine 來遍歷 DOM 樹,將它們找到的節(jié)點放入它們之間共享的通道中。import (    "golang.org/x/net/html"    "sync")func walk(doc *html.Node, ch chan *html.Node) {    var wg sync.WaitGroup    defer close(ch)    var f func(*html.Node)    f = func(n *html.Node) {        defer wg.Done()        ch <- n        for c := n.FirstChild; c != nil; c = c.NextSibling {            wg.Add(1)            go f(c)        }    }    wg.Add(1)    go f(doc)    wg.Wait()}我會這樣稱呼// get the webpage using http// parse the html into docch := make(chan *html.Node)go walk(doc, ch)for c := range ch {    if someCondition(c) {        // do something with c        // quit all goroutines spawned by walk    }}我想知道如何退出所有這些 goroutines——即關(guān)閉ch——一旦我找到了某種類型的節(jié)點或其他一些條件已經(jīng)滿足。我曾嘗試使用一個quit通道,該通道會在生成新的 goroutine 之前進行輪詢并ch在收到值時關(guān)閉,但這會導(dǎo)致競爭條件,其中一些 goroutine 嘗試在剛剛被另一個 goroutine 關(guān)閉的通道上發(fā)送。我正在考慮使用互斥鎖,但它似乎不夠優(yōu)雅并且違背了使用互斥鎖保護通道的精神。有沒有一種慣用的方法可以使用頻道來做到這一點?如果沒有,有什么辦法嗎?任何輸入表示贊賞!
查看完整描述

1 回答

?
桃花長相依

TA貢獻1860條經(jīng)驗 獲得超8個贊

context包提供了類似的功能。使用context.Context一些 Go-esque 模式,您可以實現(xiàn)您所需要的。

因此,要實現(xiàn)此功能,您的函數(shù)應(yīng)該更像:

func walk(ctx context.Context, doc *html.Node, ch chan *html.Node) {

? ? var wg sync.WaitGroup

? ? defer close(ch)


? ? var f func(*html.Node)

? ? f = func(n *html.Node) {

? ? ? ? defer wg.Done()


? ? ? ? ch <- n

? ? ? ? for c := n.FirstChild; c != nil; c = c.NextSibling {

? ? ? ? ? ? select {

? ? ? ? ? ? case <-ctx.Done():

? ? ? ? ? ? ? ? return // quit the function as it is cancelled

? ? ? ? ? ? default:

? ? ? ? ? ? ? ? wg.Add(1)

? ? ? ? ? ? ? ? go f(c)

? ? ? ? ? ? }

? ? ? ? }

? ? }


? ? select {

? ? case <-ctx.Done():

? ? ? ? return // perhaps it was cancelled so quickly

? ? default:

? ? ? ? wg.Add(1)

? ? ? ? go f(doc)

? ? ? ? wg.Wait()

? ? }

}

在調(diào)用該函數(shù)時,您將得到類似以下內(nèi)容的信息:


// ...

ctx, cancelFunc := context.WithCancel(context.Background())

walk(ctx, doc, ch)

for value := range ch {

? ? // ...

? ? if someCondition {

? ? ? ? cancelFunc()

? ? ? ? // the for loop will automatically exit as the channel is being closed for the inside

? ? }

}


查看完整回答
反對 回復(fù) 2023-06-19
  • 1 回答
  • 0 關(guān)注
  • 142 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號