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

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

通道提前終止

通道提前終止

Go
牛魔王的故事 2023-07-17 13:57:25
我正在為管道制作一系列 go 例程的原型,每個例程都執行一個轉換。例程在所有數據通過之前終止。我查了多納萬和克尼漢的書,并在谷歌上搜索了解決方案。這是我的代碼:package mainimport (    "fmt"    "sync")func main() {    a1 := []string{"apple", "apricot"}    chan1 := make(chan string)    chan2 := make(chan string)    chan3 := make(chan string)    var wg sync.WaitGroup    go Pipe1(chan2, chan1, &wg)    go Pipe2(chan3, chan2, &wg)    go Pipe3(chan3, &wg)    func (data []string) {        defer wg.Done()        for _, s := range data {            wg.Add(1)            chan1 <- s        }        go func() {            wg.Wait()            close(chan1)        }()    }(a1)}func Pipe1(out chan<- string, in <-chan string, wg *sync.WaitGroup) {    defer wg.Done()    for s := range in {        wg.Add(1)        out <- s + "s are"    }}func Pipe2(out chan<- string, in <-chan string, wg *sync.WaitGroup) {    defer wg.Done()    for s := range in {        wg.Add(1)        out <- s + " good for you"    }}func Pipe3(in <-chan string, wg *sync.WaitGroup) {    defer wg.Done()    for s := range in {        wg.Add(1)        fmt.Println(s)    }}我的預期輸出是:apples are good for youapricots are good for you運行main的結果不一致。有時我同時得到兩條線。有時我只得到蘋果。有時什么也沒有輸出。
查看完整描述

2 回答

?
四季花海

TA貢獻1811條經驗 獲得超5個贊

您的 WaitGroup.Add 和 WaitGroup.Done 調用不匹配。然而,在這種情況下,“我完成了”信號通常是通過關閉輸出通道來給出的。僅當工作在多個 goroutine 之間共享時才需要 WaitGroups(即多個 goroutine 消耗相同的通道),但這里的情況并非如此。


package main


import (

? ? "fmt"

)


func main() {

? ? a1 := []string{"apple", "apricot"}


? ? chan1 := make(chan string)

? ? chan2 := make(chan string)

? ? chan3 := make(chan string)


? ? go func() {

? ? ? ? for _, s := range a1 {

? ? ? ? ? ? chan1 <- s

? ? ? ? }


? ? ? ? close(chan1)

? ? }()


? ? go Pipe1(chan2, chan1)

? ? go Pipe2(chan3, chan2)


? ? // This range loop terminates when chan3 is closed, which Pipe2 does after

? ? // chan2 is closed, which Pipe1 does after chan1 is closed, which the

? ? // anonymous goroutine above does after it sent all values.

? ? for s := range chan3 {

? ? ? ? fmt.Println(s)

? ? }

}


func Pipe1(out chan<- string, in <-chan string) {

? ? for s := range in {

? ? ? ? out <- s + "s are"

? ? }


? ? close(out) // let caller know that we're done

}


func Pipe2(out chan<- string, in <-chan string) {

? ? for s := range in {

? ? ? ? out <- s + " good for you"

? ? }


? ? close(out) // let caller know that we're done

}

在操場上嘗試一下:https ://play.golang.org/p/d2J4APjs_lL


查看完整回答
反對 回復 2023-07-17
?
DIEA

TA貢獻1820條經驗 獲得超2個贊

您正在調用wg.Wait一個 goroutine,因此main可以在其他例程完成之前返回(因此您的程序退出)。這會導致您看到的行為,但僅從 Goroutine 中取出是不夠的。

您還濫用了WaitGroup一般性;你的AddDone調用 彼此不相關,并且你沒有那么多DoneAdd,所以 sWaitGroup永遠不會完成。如果您在循環中調用Add,則每次循環迭代也必須導致調用Done;正如您現在所擁有的,您defer wg.Done()在每個循環之前,然后Add在循環內部調用,從而產生一個Done和多個Adds。該代碼需要進行重大修改才能按預期工作。


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

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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