go - 了解 Go 中优雅的 channel 关闭

标签 go channels

this article从 Go101 站点,我已经阅读了一些关于 stopCh channel 的双重选择的技巧(在“2. 一个接收者,N 个发送者,唯一的接收者通过关闭一个额外的信号 channel ”说“请停止发送更多”部分) ).

您能否描述一下它是如何工作的,我真的需要在实际应用中使用它吗?

UPD:我没有询问 channel 关闭。我问过这部分代码的用法:

        // The try-receive operation is to try
        // to exit the goroutine as early as
        // possible. For this specified example,
        // it is not essential.
        select {
        case <- stopCh:
            return
        default:
        }

        // Even if stopCh is closed, the first
        // branch in the second select may be
        // still not selected for some loops if
        // the send to dataCh is also unblocked.
        // But this is acceptable for this
        // example, so the first select block
        // above can be omitted.
        select {
        case <- stopCh:
            return
        case dataCh <- rand.Intn(Max):
        }

双重选择 stopCh 的实际用例是什么?

最佳答案

这里的关键是了解如果可以进行多种情况,即伪随机,select 的行为如何:

  1. If one or more of the communications can proceed, a single one that can proceed is chosen via a uniform pseudo-random selection.

https://golang.org/ref/spec#Select_statements

select {
case <- stopCh:
    return
case dataCh <- rand.Intn(Max):
}

只有第二个 select 语句,在 stopCh 关闭后,如果至少满足以下条件之一,则两种情况都可以继续进行:

  1. dataCh 已缓冲且未满
  2. 即使在 stopCh 关闭后,至少有一个 goroutine 尝试从 dataCh 接收数据

如果不显式检查 stopCh,即使 goroutine 预期退出,运行时也可能(尽管不太可能)重复选择第二种情况。如果 goroutine 碰巧在每次迭代中发射导弹,您就会明白这可能是个问题。

如果可以肯定地排除这两个条件,则可以省略第一个 select 语句,因为不可能两种情况都准备好继续进行。 Go101 文章只是展示了一个保证有效的解决方案,没有做任何假设。

这种模式在现实世界的代码中并不少见,通常与上下文取消有关:

func f(ctx context.Context, ch chan T) {
    for {
        // Make sure we don't shoot after ctx has been
        // canceled, even if a target is already lined up.
        select {
        case <-ctx.Done():
            return
        default:
        }

        // Or, equivalently: if ctx.Err() != nil { return }


        select {
        case <-ctx.Done():
            return
        case t := <-ch:
            launchMissileAt(t)
        }
    }
}

关于go - 了解 Go 中优雅的 channel 关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55709797/

相关文章:

ios - 如何向这个 Firebase Swift Chat 应用添加多个房间

html - 404页面未找到-去渲染css文件

OpenCV:合并分离的 JPEG 拜耳 channel

go - 如何在 atom.io 下运行我的 golang 主包?

api - goroutines与数据列表并行运行post api

python - 值错误 : number of input channels does not match corresponding dimension of filter, 512 != 3

go - 根据选择的使用情况,向无缓冲 channel 写入两次会导致不同的结果。为什么?

转到缓冲 channel 通过选择

cookies - Golang中如何查看cookieJar的内容?

golang编译错误: can't find import