Go通道未接收/打印发送到通道的最后一个值
下面是一段代码,它在推送到通道时输出整数列表。否则,select将检查并打印必要的超时消息Go通道未接收/打印发送到通道的最后一个值,go,channel,goroutine,Go,Channel,Goroutine,下面是一段代码,它在推送到通道时输出整数列表。否则,select将检查并打印必要的超时消息 package main import ( "fmt" "sync" "time" ) var wg sync.WaitGroup func main() { wg.Add(1) c := make(chan int) go readFromChannel(c, time.After(time.Duration(2)*time.Second)) //
package main
import (
"fmt"
"sync"
"time"
)
var wg sync.WaitGroup
func main() {
wg.Add(1)
c := make(chan int)
go readFromChannel(c, time.After(time.Duration(2)*time.Second))
// time.Sleep(time.Duration(5) * time.Second) //Talking about uncommenting this line
c <- 10
c <- 20
c <- 30
c <- 40
c <- 50
wg.Wait()
}
func readFromChannel(c chan int, ti <-chan time.Time) {
defer wg.Done()
go func() {
for {
select {
case x := <-c:
fmt.Println("Read", x)
case t :=<-ti:
fmt.Println("TIMED OUT with "+t.String())
}
}
}()
}
但当我取消注释代码中提到的使主例程休眠5秒的行(注释/行号16)时,输出更改为:
TIMED OUT with 2009-11-10 23:00:02 +0000 UTC m=+2.000000001
Read 10
Read 20
Read 30
Read 40
我想了解为什么最后一次读取的50没有在第二种情况下打印。问题是您的wg.Done在错误的位置。它必须在您的goroutine中,但您在goroutine启动之前就执行了它,因此您的程序可能会在执行任何工作之前退出
更改此项:
defer wg.Done()
go func() {
为此:
go func() {
defer wg.Done()
当然,您将有一个无限运行的goroutine,因为for循环没有退出条件。您需要添加一个,可能是通过检查频道关闭:
select {
case x, ok := <-c:
if !ok { // channel was closed
return
}
fmt.Println("Read", x)
case t :=<-ti:
fmt.Println("TIMED OUT with "+t.String())
}
然后告诉你的主要围棋程序在完成后关闭频道:
c <- 40
c <- 50
close(c) // We're done, so tell the goroutine to finish up
wg.Wait() // But wait until it's done
伟大的很好。还有一个问题。使用你的代码,我改变了如果!ok{return}如果ok{fmt.printlread,x}。而且它仍然运行良好。是什么打破了这个循环?当频道关闭时,select中是否有任何BTS处理?在这种情况下,中断循环的是程序退出。
c <- 40
c <- 50
close(c) // We're done, so tell the goroutine to finish up
wg.Wait() // But wait until it's done