Go 选择和上下文。上下文完成频道

Go 选择和上下文。上下文完成频道,go,concurrency,channel,Go,Concurrency,Channel,我不明白context.context中的Done()频道如何按预期工作。模块文档(以及使用它的源代码)依赖于此模式: select { case <-ctx.Done(): return ctx.Err() case results <- result: } 选择{ 病例本例: case <-ctx.Done(): 请注意,您必须向第一个select添加一个default分支,否则它将阻塞,直到上下文被取消。如果存在default分支且上下文尚未被取消,则选择d

我不明白
context.context
中的
Done()
频道如何按预期工作。模块文档(以及使用它的源代码)依赖于此模式:

select {
case <-ctx.Done():
    return ctx.Err()

case results <- result:
}
选择{
病例本例:

case <-ctx.Done():
请注意,您必须向第一个select添加一个
default
分支,否则它将阻塞,直到上下文被取消。如果存在
default
分支且上下文尚未被取消,则选择
default
分支,因此控制流可以转到第二个
select

见相关问题:


“该模式如何保证我不会通过管道发送结果?”,没有模式可以,这是并发的本质。您可以对“该模式如何保证我不会通过管道发送结果”做出一些保证:这取决于您如何创建
result
。如果
result
未缓冲,则仅当某个接收操作解决时,发送操作才会继续。如果
result
具有缓冲区,则它可能包含一个(或多个)值;但是,如果在
select
语句中执行的分支是
,您仍然可以保证不会从
结果中弹出任何值,除非它可能在发送前一刻被取消,或者在检查缓冲通道后立即准备发送。切断总是任意的,并且只需要接受你可能有“亲密接触”如果您不打算等待响应,这并不重要。我不确定我是否理解第一个
select
如何帮助。如果不同线程中的另一个例程关闭语句之间的通道,我不是处于相同的情况吗?第一个
select
帮助您,如果上下文已经取消,您将不会在尝试在
结果
上发送一个值。如果执行
选择
时上下文已被取消,则无法保证如果两者都准备好继续,则选择哪种情况。
<-ctx.Done()
select {
case <-ctx.Done():
    return ctx.Err()
default:
}

select {
case <-ctx.Done():
    return ctx.Err()

case results <- result:
}