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

这是一段代码,它输出推送到通道的整数列表。否则,选择检查并打印必要的超时消息。


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())

            }

        }

    }()


}

另外,这里还有相同的游乐场链接: https: //play.golang.org/p/4hNWze4Pfwr 此代码输出整数列表,例如


Read 10

Read 20

Read 30

Read 40

Read 50

但是,当我取消注释使主例程进入睡眠状态 5 秒的行(在代码中称为注释/行号 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在第二种情况下没有打印最后一个。


翻翻过去那场雪
浏览 90回答 1
1回答

大话西游666

问题是你的wg.Done()位置不对。它必须在你的 goroutine 中,但是你在 goroutine 启动之前执行它,所以你的程序很可能在做任何工作之前退出。改变这个:defer wg.Done()go func() {对此:go func() {&nbsp; &nbsp; defer wg.Done()当然,你将拥有一个无限运行的 goroutine,因为你的for循环没有退出条件。您需要添加一个,可能是通过检查通道关闭来添加:&nbsp; &nbsp; &nbsp; &nbsp; select {&nbsp; &nbsp; &nbsp; &nbsp; case x, ok := <-c:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if !ok { // channel was closed&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("Read", x)&nbsp; &nbsp; &nbsp; &nbsp; case t :=<-ti:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("TIMED OUT with "+t.String())&nbsp; &nbsp; &nbsp; &nbsp; }然后告诉你的主 go 例程在完成后关闭通道:c <- 40c <- 50close(c)&nbsp; // We're done, so tell the goroutine to finish upwg.Wait() // But wait until it's done
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go