首页 > 解决方案 > 合并两个关闭通道

问题描述

有两个通道将用于通过关闭它们来发出信号。如果其中至少一个被关闭,如何从它们中创建一个将关闭的通道。这段代码说明了我想做的事情:

func MergeChans(c1 chan struct{}, c2 chan struct{}) chan struct{} {
    c3 := make(chan struct{})
    go func() {
        select {
        case <-c1: close(c3)
        case <-c2: close(c3)
        }
    }()
    return c3
}

是否可以在没有子程序的情况下实现这一目标?

标签: goconcurrencychannel

解决方案


如果您想在需要关闭之前返回“合并”通道,则不。

但这不是问题,你在里面启动的 goroutine 将使用 0 CPU 资源。你不应该担心那个。

一旦其中一个通道关闭,函数将结束,因此 goroutine 将正确终止。您只需确保至少有一个通道被关闭。如果你不能保证这一点,goroutine 将永远不会终止并且永远不会被垃圾收集。如果您不控制通道,则可以传递第三个通道(或context.Context值)以提供正确终止的方式,例如:

func MergeChans(c1, c2, shutdown chan struct{}) chan struct{} {
    c3 := make(chan struct{})
    go func() {
        select {
        case <-c1:
            close(c3)
        case <-c2:
            close(c3)
        case <-shutdown:
        }
    }()
    return c3
}

如果你想避免额外的 goroutine,那么不要合并它们(case在需要监控的地方添加 2 s)。


推荐阅读