【问题标题】:Go, passing data to channelGo,将数据传递到通道
【发布时间】:2018-06-17 07:29:55
【问题描述】:

我有一个问题。这是示例:https://play.golang.org/p/QSWY2INQuSE

func Avg(c chan string, wg *sync.WaitGroup) {
    defer wg.Done()
    c <- "test"
}

func main() {
    var wg sync.WaitGroup
    c := make(chan string)

    timer1 := time.NewTicker(5 * time.Second)

    for {
        select {
        case <-timer1.C:
            wg.Add(1)
            go Avg(c, &wg)
            wg.Wait()
        }
    }
    fmt.Println(<-c)
}

为什么数据没有到达fmt.Println(&lt;-c)

谢谢!

【问题讨论】:

    标签: go concurrency channel goroutine


    【解决方案1】:

    因为你有一个无穷无尽的for,所以最后一个fmt.Println() 语句永远不会到达。

    如果您想执行最后一个fmt.Println() 语句,则必须跳出循环,例如:

    loop:
        for {
            select {
            case <-timer1.C:
                wg.Add(1)
                go Avg(c, &wg)
                wg.Wait()
                break loop
            }
        }
        fmt.Println(<-c)
    

    请注意,您必须使用标签,否则break 只会跳出select 语句(而不是跳出for 循环)。

    还请注意,仅此一项是行不通的,因为通道没有缓冲,因此Avg() 将永远被阻塞,尝试在c 上发送一个值,而没有人尝试从它接收。

    如果你创建要缓冲的通道,这个简单的例子就可以工作:

    c := make(chan string, 1) // Buffer for 1 value
    

    现在它可以工作并打印(在Go Playground 上试用):

    test
    

    【讨论】:

    • 嘿,但在这种情况下,当主函数退出时,将停止并且不会每秒触发一次自动收录机。怎么使用那个ticker会每秒触发一次?
    • @MihaZoubek 如果您不想在第一次滴答后退出,那么显然不要“打破”循环。但是随后您将需要(另一个)goroutine 同时“耗尽”c 通道,否则如果没有从它接收第二次发送,它将永远阻塞。
    猜你喜欢
    • 2016-04-11
    • 2014-05-02
    • 1970-01-01
    • 1970-01-01
    • 2014-03-30
    • 2014-01-17
    • 1970-01-01
    • 1970-01-01
    • 2021-09-13
    相关资源
    最近更新 更多