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 关注
- 73 浏览
添加回答
举报