当前位置: 首页 > 面试题库 >

在一个通道上监听多个goroutine

刁浩言
2023-03-14
问题内容

我有多个goroutine试图同时在同一频道上接收。似乎最后一个在通道上开始接收的goroutine获得了值。这是语言规范中的某个地方,还是未定义的行为?

c := make(chan string)
for i := 0; i < 5; i++ {
    go func(i int) {
        <-c
        c <- fmt.Sprintf("goroutine %d", i)
    }(i)
}
c <- "hi"
fmt.Println(<-c)

输出:

goroutine 4

操场上的例子

编辑:

我只是意识到它比我想的还要复杂。该消息在所有goroutine中传递。

c := make(chan string)
for i := 0; i < 5; i++ {
    go func(i int) {
        msg := <-c
        c <- fmt.Sprintf("%s, hi from %d", msg, i)
    }(i)
}
c <- "original"
fmt.Println(<-c)

输出:

original, hi from 0, hi from 1, hi from 2, hi from 3, hi from 4

操场上的例子


问题答案:

是的,它很复杂,但是有一些经验法则可以使事情变得简单得多。

  • 宁愿使用 传递给go-routine 的通道的形式参数, 而不是访问全局范围内的通道。您可以通过这种方式获得更多的编译器检查,以及更好的模块化。
  • 避免在特定的例行程序 (包括“主要” 程序)的同一通道上进行读取和写入 。否则,死锁风险更大。

这是应用这两个准则的程序的替代版本。此案例演示了频道上的许多作家和一位读者:

c := make(chan string)

for i := 1; i <= 5; i++ {
    go func(i int, co chan<- string) {
        for j := 1; j <= 5; j++ {
            co <- fmt.Sprintf("hi from %d.%d", i, j)
        }
    }(i, c)
}

for i := 1; i <= 25; i++ {
    fmt.Println(<-c)
}

http://play.golang.org/p/quQn7xePLw

它创建五个go例程写入单个通道,每个例程写入五次。主例程会读取所有25条消息-您可能会注意到它们出现的顺序通常不是顺序的(即,并发很明显)。

此示例演示了Go频道的功能:可能有多个作者共享一个频道;Go将自动插入邮件。

同样适用于一个频道上的一位作者和多个读者,如此处的第二个示例所示:

c := make(chan int)
var w sync.WaitGroup
w.Add(5)

for i := 1; i <= 5; i++ {
    go func(i int, ci <-chan int) {
        j := 1
        for v := range ci {
            time.Sleep(time.Millisecond)
            fmt.Printf("%d.%d got %d\n", i, j, v)
            j += 1
        }
        w.Done()
    }(i, c)
}

for i := 1; i <= 25; i++ {
    c <- i
}
close(c)
w.Wait()

此第二个例子包括施加在主够程等待,否则退出及时并引起其他五个够程要提前终止_(由于[ olov]此校正)_。

在两个示例中,都不需要缓冲。通常,将缓冲仅视为性能增强器是一个很好的原则。如果你的程序不会死锁 没有 缓冲区,也不会发生死锁 缓冲区是(但反之
并不 总是正确的)。因此,作为 另一条经验法则,开始时不要缓冲,然后根据需要稍后添加



 类似资料:
  • 例如,我可以启动两个程序侦听端口371。第二个没有任何问题地启动并接收传入连接,而第一个没有。一旦最后开始的进程终止,第一个接收它们。 假设这是Windows(XP)行为,它怎么可能是安全的行为呢?这意味着人们可以“过载”任何已经侦听的端口,而不是获得通常的“地址已经在使用”错误消息,并简单地绕过防火墙,规则只是说“允许端口371上的任何传入TCP连接”。

  • 问题内容: 我设法用Jsch通过ssh执行了一条命令,但是当我尝试执行第二条命令时却失败了 为了调试,我将此问题归结为以下几行: 这主要是官方的Exec示例,但这给了我以下输出: 第一个命令成功执行,第二个则没有成功。 有任何想法吗 ? 问题答案: 嘿,jsch和Ubuntu完全一样。(如何)解决了?为每个执行执行新会话会浪费太多时间?此刻,我捕获了jsch异常并搜索“会话未关闭”,然后我重新连接

  • 我是新来的,想知道一些很基本的问题,我不能弄清楚。 为了发挥作用(对实际需要的抽象),我需要: 用常数固定的元素初始化字符串片断 遍历此切片并为每个元素运行一个goroutine 每个goroutine将花费一定的时间来处理元素(随机秒持续时间) 作业完成后,我希望goroutine将结果推送到一个通道 然后我需要捕获来自这个通道的所有结果(在一个从主goroutine调用的函数中),将它们附加到

  • 问题内容: 是否可以在一个应用程序中绑定和侦听Linux中的多个端口? 问题答案: 对于您要收听的每个端口,您: 使用创建一个单独的套接字。 将其绑定到适当的端口。 调用套接字,以便它设置一个侦听队列。 那时,您的程序正在侦听多个套接字。为了接受这些套接字上的连接,您需要知道客户端要连接到哪个套接字。就是这样。碰巧的是,我有代码可以完全做到这一点,所以这是一个完整的经过测试的示例,它等待多个套接字

  • 本文向大家介绍详解nginx同一端口监听多个域名和同时监听http与https,包括了详解nginx同一端口监听多个域名和同时监听http与https的使用技巧和注意事项,需要的朋友参考一下 详解nginx同一端口监听多个域名和同时监听http与https 1、同一端口监听多个域名 如今公网ip资源越来越珍贵,多域名监听应用非常广泛,就是用一个端口,比如80或者443,监听多个入口域名。如下: 在

  • 我试图用Laravel Echo在私人频道上收听,但它不只在私人频道上收听,公共频道工作正常。 我也在使用Beyondcode/Laravel-WebSocket包,它在WebSocket仪表板面板中显示了所有的连接和事件。它显示了包本身的私有连接、我的公共连接和所有触发的事件(私有和公共),但没有显示我的私有连接 如果触发该事件并将数据保存在数据库中,则所有操作都完全正常,只是在视图中,我没有从