【问题标题】:Two routines communicating on the same channel两个例程在同一通道上通信
【发布时间】:2014-08-28 02:30:55
【问题描述】:

我有一个函数,给定一个切片和一个数组,将切片的元素一个一个发送到通道

Link to playground

package main

import (
    "fmt"
)

var list1 = []string{"1", "2", "4"}

var list2 = []string{"11", "22", "44"}

func throw(ch chan string, list []string) {
    for _, el := range list {
        fmt.Println("Thrown ", el)
        ch <- el

    }
    close(ch)
    return
}

func main() {
    c := make(chan string)
    go throw(c, list1)
    go throw(c, list2)
    for i := range c {
        fmt.Println("received ", i)
    }
}

有时通道会关闭,但其中一个功能仍需要向其发送数据。我该如何处理?分开通道似乎是这里最合理的选择,但我希望两个数据都通过同一个通道。

【问题讨论】:

    标签: concurrency go channel goroutine


    【解决方案1】:

    Go 期望通道发送端的代码知道通道是否已关闭。所以像你的 sn-p 这样的代码,每个 goroutine 可以关闭通道而不考虑另一个是错误的。

    一种解决方案是使用sync.WaitGroup 来协调每个 goroutine 何时完成,并让第三个 goroutine 执行关闭。所以你应该修改你的throw 函数看起来像:

    func throw(ch chan string, list []string, wg *sync.WaitGroup) {
        defer wg.Done()
        // current body of function, without the close() call
    }
    

    并将生成 goroutine 的代码更改为以下内容:

    var wg sync.WaitGroup
    wg.Add(2)
    go throw(c, list1, &wg)
    go throw(c, list2, &wg)
    go func() {
        wg.Wait()
        close(c)
    }()
    

    这样你的频道只有在其他两个 goroutine 完成后才会关闭。你可以在这里试验你的例子的这个修改版本:http://play.golang.org/p/nUiwjGglgU

    【讨论】:

    • 如果您知道该频道有多少项目,那将是可行的,是的。在这个人为的例子中可能是这样,但肯定不是一般情况。
    • 当然!这完全取决于任务的条件。您的解决方案更通用,所以我投了赞成票
    猜你喜欢
    • 1970-01-01
    • 2012-08-18
    • 2012-05-01
    • 1970-01-01
    • 2015-10-05
    • 1970-01-01
    • 1970-01-01
    • 2016-12-28
    • 1970-01-01
    相关资源
    最近更新 更多