2 回答

TA貢獻1795條經驗 獲得超7個贊
該代碼邏輯有許多缺陷 - 其中一些是:
1- 由于messageCh被緩沖,此代碼沒有阻塞:
for i := 0; i < 10; i++ {
messageCh <- i
}
所以下一個代碼在快速運行路徑中:
disconnectCh <- struct{}{}
如果您進行disconnectCh緩沖,則此行也不會阻塞運行,并且該SelectDemo函數可能會在運行wg.Add(1).
所以:你必須把:
wg.Add(1)
前
go func() {
2-即使使用wg.Add(1)之前的go func() { 代碼-
您也有:
defer close(messageCh)
defer close(disconnectCh)
這將在函數返回時關閉兩個通道SelectDemo這select是一個隨機選擇,因為兩個通道都準備好了:
fmt.Println(" goroutine")
for {
select {
case v := <-messageCh:
fmt.Println(v)
case <-disconnectCh:
第二個選擇很可能是:
for {
select {
case v := <-messageCh:
fmt.Println(v)
default:
fmt.Println(" disconnection, return")
wg.Done()
return
}
}
將在messageCh關閉后0永遠運行,在讀取通道數據后永遠返回:
case v := <-messageCh:
fmt.Println(v)

TA貢獻2080條經驗 獲得超4個贊
程序執行速度快
訪問網址:https ://pkg.go.dev/sync#WaitGroup.Add
請注意,當計數器為零時發生的具有正增量的調用必須在等待之前發生。具有負增量的調用或具有正增量的調用在計數器大于零時開始,可能隨時發生。通常這意味著對 Add 的調用應該在創建 goroutine 的語句或其他要等待的事件之前執行。如果重用 WaitGroup 來等待多個獨立的事件集,則必須在所有先前的 Wait 調用都返回后發生新的 Add 調用。請參閱 WaitGroup 示例。
func SelectDemo(wg *sync.WaitGroup) {
messageCh := make(chan int, 10)
disconnectCh := make(chan struct{}, 1)
// go routine won't run if channel is buffered
//disconnectCh := make(chan struct{}, 1)
wg.Add(1)
defer close(messageCh)
defer close(disconnectCh)
go func() {
fmt.Println(" goroutine")
for {
select {
case v := <-messageCh:
fmt.Println(v)
case <-disconnectCh:
fmt.Println(" disconnectCh")
// empty the buffered channel before exiting
fmt.Println(" disconnection, return")
wg.Done()
return
}
}
}()
fmt.Println("Sending ints")
for i := 0; i < 10; i++ {
messageCh <- i
}
//Delay sending exit signal
time.Sleep(3 * time.Second)
fmt.Println("Sending done")
disconnectCh <- struct{}{}
}
我修改了你的代碼
再試一次?。?!
- 2 回答
- 0 關注
- 111 瀏覽
添加回答
舉報