为了账号安全,请及时绑定邮箱和手机立即绑定

Go 通道未接收/打印发送到通道的最后一个值

Go 通道未接收/打印发送到通道的最后一个值

Go
翻翻过去那场雪 2023-07-10 16:45:30
这是一段代码,它输出推送到通道的整数列表。否则,选择检查并打印必要的超时消息。package mainimport (    "fmt"    "sync"    "time")var wg sync.WaitGroupfunc 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())            }        }    }()}另外,这里还有相同的游乐场链接: https: //play.golang.org/p/4hNWze4Pfwr 此代码输出整数列表,例如Read 10Read 20Read 30Read 40Read 50但是,当我取消注释使主例程进入睡眠状态 5 秒的行(在代码中称为注释/行号 16)时,输出更改为:TIMED OUT with 2009-11-10 23:00:02 +0000 UTC m=+2.000000001Read 10Read 20Read 30Read 40我想了解为什么Read 50在第二种情况下没有打印最后一个。
查看完整描述

1 回答

?
大话西游666

TA贡献1817条经验 获得超14个赞

问题是你的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


查看完整回答
反对 回复 2023-07-10
  • 1 回答
  • 0 关注
  • 89 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信