dongyizhuang0134 2019-08-10 14:42
浏览 42
已采纳

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

Here's a piece of code which outputs a list of integers as pushed to a channel. Else a select checks and prints necessary timeout message.

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

}

Also here's the playground link for the same : https://play.golang.org/p/4hNWze4Pfwr This code outputs list of integer like

Read 10
Read 20
Read 30
Read 40
Read 50

But when I un-comment the line that make the main routine go to sleep for 5 sec(mentioned in the code as comment/line number 16), output changes to :

TIMED OUT with 2009-11-10 23:00:02 +0000 UTC m=+2.000000001
Read 10
Read 20
Read 30
Read 40

I want to understand why the last Read 50 is not being printed in second case.

  • 写回答

1条回答 默认 最新

  • doubao12345 2019-08-10 15:12
    关注

    The problem is that your wg.Done() is in the wrong place. It must be in your goroutine, but you're executing it before the goroutine even starts, so your program is liable to exit before doing any work.

    Change this:

    defer wg.Done()
    go func() {
    

    to this:

    go func() {
        defer wg.Done()
    

    Of course then you'll have an infinitely running goroutine, because your for loop has no exit condition. You'll need to add one, probably by checking for the channel closing:

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

    Then tell your main go routine to close the channel when it's done:

    c <- 40
    c <- 50
    close(c)  // We're done, so tell the goroutine to finish up
    wg.Wait() // But wait until it's done
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器