跨频道选择更好还是使用选择更好?

问题描述 投票:0回答:3

伙计们,我想知道如果我只有一种情况(我的频道)并用给定频道的关闭来表示结束,是否最好在频道范围内进行选择或使用选择?

举例:

1. https://play.golang.org/p/3ZFdbgHSKyN

go func() {
    for v := range ch {
        // do some stuff
    }
}()

2. https://play.golang.org/p/iCCkDge8j72

go func() {
    for {
        select {
        case v, ok := <-ch:
            if !ok {
                return
            }

            // do some stuff
        }
    }
}()

哪种解决方案是首选,为什么?请考虑这样一个事实:goroutine 本身可能会产生很多次(很多工作线程)。

go
3个回答
19
投票

除非有另一个选择分支,否则使用以下内容:

for v := range ch {
    // do some stuff
}

代码比问题中提出的 for/select 更简单、更容易理解。

如果由于某种原因需要在循环内进行接收,请使用以下代码:

 for  { 
     // do some stuff
     v, ok := <-ch
     if !ok { 
        break 
     } 
     // do some other stuff
 }

根据经验,应避免使用单分支选择语句。具有单个分支的选择在功能上与单独的分支相同。


0
投票

如果您只是在不需要返回值的完成通道上等待,那么您可以完全放弃 for 循环,因为 chan 将阻塞。例如

// Verbose
go func() {
    for {
        select {
            case <-blah.Context.Done():
                // Cleanup/Close
                return
        }
    }
}()

// Simplified
go func() {
    <-blah.Context.Done():
    // Cleanup/Close (No return required either)
}()

0
投票

我注意到使用 select 而不是 range 有一个区别,即使是单个通道。当接收到信号并触发关闭通道并重新分配它的代码逻辑时,范围循环将停止,因为通道已关闭。使用 for select 它将继续并在分配给该变量的新通道上运行。

在我的例子中,我使用 select 重新连接到 RabbitMQ 服务器。您可以在那里注册一个在连接关闭时接收信号的通道。然而,当连接关闭时,通道也会关闭,因此再次连接时需要重新声明它。因此,在我的情况下范围是不可行的,因为它停止了重新连接循环。

© www.soinside.com 2019 - 2024. All rights reserved.