我有两个渠道,上游和下游。我的目标是从上游读取数据并将它们传递给下游。但是,当上下文被取消时,我想优雅地退出而不会出现死锁。我试图变得“聪明”并做了类似以下的事情。func main() { upstream := make(chan struct{}) ctx, cancel := context.WithCancel(context.Background()) go func() { <-time.After(5 * time.Second) cancel() }() // Buffered downstream ensures no blocking in this scenario downstream := make(chan struct{}, 1) select { case <-ctx.Done(): log.Println("context is killed") case downstream <- <-upstream: log.Println("transferred value from upstream to downstream") }}然后我陷入了僵局。但是,如果我不再懒惰并执行以下操作,func main() { upstream := make(chan struct{}) ctx, cancel := context.WithCancel(context.Background()) go func() { <-time.After(5 * time.Second) cancel() }() // Buffered downstream ensures no blocking in this scenario downstream := make(chan struct{}, 1) select { case <-ctx.Done(): log.Println("context is killed") case val := <-upstream: downstream <-val log.Println("transferred value from upstream to downstream") }}它完美地退出,没有死锁。请您赐教,两者之间的主要区别是什么downstream <- <-upstream和val := <-upstreamdownstream <-val
1 回答

米琪卡哇伊
TA贡献1998条经验 获得超6个赞
select 语句不是在<-upstream接收语句上运行,而是在downstream <-send 语句上运行。
在选择案例可以确定downstream <-发送语句是否准备好之前,它首先必须评估参数表达式,即<-upstream. 因为没有任何东西被发送到upstream,所以该评估被阻止。这意味着您根本不会接触到选定的案例。
等效的多行代码看起来像这样,这很明显为什么它不起作用。
val := <-upstream
select {
case <-ctx.Done():
log.Println("context is killed")
case downstream <- val:
log.Println("transferred value from upstream to downstream")
}
- 1 回答
- 0 关注
- 98 浏览
添加回答
举报
0/150
提交
取消