亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

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

我應該在哪個函數中傳遞 WaitGroup?

我應該在哪個函數中傳遞 WaitGroup?

Go
小唯快跑啊 2023-06-05 18:02:16
我做了一個簡單的代碼示例來了解管道的用法,就在這里。package mainimport (    "fmt"    "sync"    "time")func main() {    ch1 := make(chan int, 10) // Use buffered channel so as to avoid clogging    ch2 := make(chan string, 10)    var wg sync.WaitGroup    for i := 0; i < 3; i++ {        wg.Add(1)        go func1(i, ch1, &wg)        go func2(ch1, ch2)    }    wg.Wait()    close(ch1)    for val := range ch2 {        fmt.Println(val)    }}func func1(seconds int, ch chan<- int, wg *sync.WaitGroup) {    defer wg.Done()    time.Sleep(time.Duration(seconds) * time.Second)    fmt.Println(seconds)    ch <- seconds}func func2(ch1 chan int, ch2 chan string) {    for range ch1 {        ch2 <- "hello"    }    close(ch2)}現在,問題是我沒有得到一致的輸出(我知道這是一些并發問題,我還沒有完全理解)。輸出> go run pipeline-loop.go 012hellohello> go run pipeline-loop.go 012hellohellohello> go run pipeline-loop.go 012hellohello> go run pipeline-loop.go 012hellohello> go run pipeline-loop.go 012hellohellopanic: close of closed channelgoroutine 6 [running]:main.func2(0xc00006c000, 0xc000056180)    /home/projects/go-tuts/pipeline-loop.go:36 +0x72created by main.main    /home/projects/go-tuts/pipeline-loop.go:16 +0x10fexit status 2另一個人更改了代碼(它正在運行)并放在func2循環之外,但我func2希望func1.問題所以,我想了解應該在哪里使用WaitGroup和?close(ch)謝謝。Temporarya(一個 golang noobie)
查看完整描述

2 回答

?
吃雞游戲

TA貢獻1829條經驗 獲得超7個贊

您的代碼中存在多個問題。

在循環中,您正在生成多個 (3) goroutines 運行func2,并且在中func2,您將數據發送到ch2并調用close(ch2)。這是個問題。ch2當一個 goroutine 將數據發送到時,另一個goroutine 可能會關閉該通道,這會導致:

panic: close of closed channel


goroutine 6 [running]:

main.func2(0xc00006c000, 0xc000056180)

? ? /home/projects/go-tuts/pipeline-loop.go:36 +0x72

created by main.main

? ? /home/projects/go-tuts/pipeline-loop.go:16 +0x10f

exit status 2

通常,您不需要多次關閉通道 - 您只需要在它們全部完成后關閉它們。WaitGroup為此你需要另一個;您需要將兩個函數都傳遞給 a?WaitGroup。

更新:

我個人使用一種“工作”模式,將數據生成到同一通道,并且在完成所有工作后需要關閉該通道:

for something {

? ? wg.Add(1)

? ? go func(i int) {

? ? ? ? work(ch)

? ? ? ? wg.Done()

? ? }

}


go func() {

? ? wg.Wait()

? ? close()

}()

我認為保持 API 清潔是一個好主意,WorkGroup因為WorkGroup它是關于如何同步工作而不是如何完成工作的。


我已將您的代碼更改為這種模式:https ://play.golang.org/p/vdCNsxWhgyQ


查看完整回答
反對 回復 2023-06-05
?
肥皂起泡泡

TA貢獻1829條經驗 獲得超6個贊

我懷疑您只希望一個通道從 ch1 讀取并寫入 ch2。創建 3 個 go-routines 來做同樣的事情沒有多大意義(而且你最終也會關閉相同的通道 multiple time 這會導致恐慌,正如 leaf bebop 指出的那樣)


func main() {

    ch1 := make(chan int, 10) // Use buffered channel so as to avoid clogging

    ch2 := make(chan string, 10)

    var wg sync.WaitGroup

    for i := 0; i < 3; i++ {

        wg.Add(1)

        go func1(i, ch1, &wg)

    }

    go func2(ch1, ch2)

    wg.Wait()

    close(ch1)

    for val := range ch2 {

        fmt.Println(val)

    }

}


查看完整回答
反對 回復 2023-06-05
  • 2 回答
  • 0 關注
  • 192 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號