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

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

為什么我的“完成”頻道會隨機關閉?

為什么我的“完成”頻道會隨機關閉?

Go
ITMISS 2023-08-14 14:40:11
我構建了以下 go 代碼。這個想法是構建一個完成通道和一個生成 int 通道的生成器。將它們鏈接到一個 2 階段管道 chanNumbers := pipelineb(done, pipelinea(done, gen(done)))幾秒鐘后,取消已完成的通道。我希望看到生成器和管道的兩級取消并返回,但文本“PipeX 現在終止”僅隨機出現,我真的不明白為什么。有人有主意嗎?package mainimport (    "fmt"    "time")func gen(done <-chan interface{}) <-chan int {    ret := make(chan int)    cx := 0    go func() {        for {            select {            case <-done:                fmt.Println("**Generator Terminates now")                time.Sleep(2 * time.Second)                fmt.Println("**Generator has terminated now")                close(ret)                return            case ret <- cx:                fmt.Printf("Gen : we push %d \n", cx)                cx = cx + 1            }        }    }()    fmt.Println("Generator has created and returned its channel")    return ret}func pipea(done <-chan interface{}, in <-chan int) <-chan int {    ret := make(chan int)    go func() {        for {            select {            case <-done:                fmt.Println("**pipeA terminates")                time.Sleep(2 * time.Second)                fmt.Println("**pipeA has terminated now")                close(ret)                return            case tmp, ok := (<-in):                if ok {                    fmt.Printf("pipeA : we push %d \n", tmp)                    ret <- tmp                } else {                    in = nil                }            }        }    }()    return ret}func pipeb(done <-chan interface{}, in <-chan int) <-chan int {    ret := make(chan int)    go func() {        for {            select {            case <-done:                fmt.Println("**pipeB terminates")                time.Sleep(2 * time.Second)                fmt.Println("**pipeB has terminated now")                close(ret)
查看完整描述

1 回答

?
收到一只叮咚

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

您有四個正在運行的 go 例程:

  1. gen,你的生成器,寫入無緩沖的輸出通道,直到done

  2. pipeA,從 讀取gen,寫入無緩沖的輸出通道,直到done

  3. pipeB,從 讀取pipeA,寫入無緩沖的輸出通道,直到done

  4. main,從pipeB讀到done

現在,當您關閉時done,它完全取決于 go 例程看到它的順序。

如果main是第一個看到它done已關閉,它將打破 for 循環并停止消耗pipeB。但是如果pipeB仍然嘗試寫入輸出通道(ret <- tmp),它將在那里阻塞;所以它永遠不會到達該<- done部分。

有兩個選項可以解決此問題:

  1. 只在你的生成器中監聽done,并讓其他 go 例程使用for n := range in { }.

  2. select將您的發送邏輯也放入 a 中,以便您的生成器和管道可以檢測何時done關閉。

或者,您可能希望使用緩沖輸出通道,但即使如此,此問題仍然可能發生。


查看完整回答
反對 回復 2023-08-14
  • 1 回答
  • 0 關注
  • 133 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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