Go channel 不是 receiving/printing 发送到 channel 的最后一个值
Go channel not receiving/printing last value sent to channel
这是一段代码,它输出推送到频道的整数列表。否则 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))
// 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())
}
}
}()
}
这里还有游乐场 link 同样的:https://play.golang.org/p/4hNWze4Pfwr
此代码输出整数列表,如
Read 10
Read 20
Read 30
Read 40
Read 50
但是当我取消注释使主例程进入睡眠 5 秒的行时(在代码中提到为 comment/line 数字 16),输出更改为:
TIMED OUT with 2009-11-10 23:00:02 +0000 UTC m=+2.000000001
Read 10
Read 20
Read 30
Read 40
我想了解为什么最后一个 Read 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())
}
然后告诉您的主要 go 例程在完成后关闭通道:
c <- 40
c <- 50
close(c) // We're done, so tell the goroutine to finish up
wg.Wait() // But wait until it's done
这是一段代码,它输出推送到频道的整数列表。否则 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))
// 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())
}
}
}()
}
这里还有游乐场 link 同样的:https://play.golang.org/p/4hNWze4Pfwr 此代码输出整数列表,如
Read 10
Read 20
Read 30
Read 40
Read 50
但是当我取消注释使主例程进入睡眠 5 秒的行时(在代码中提到为 comment/line 数字 16),输出更改为:
TIMED OUT with 2009-11-10 23:00:02 +0000 UTC m=+2.000000001
Read 10
Read 20
Read 30
Read 40
我想了解为什么最后一个 Read 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())
}
然后告诉您的主要 go 例程在完成后关闭通道:
c <- 40
c <- 50
close(c) // We're done, so tell the goroutine to finish up
wg.Wait() // But wait until it's done