kSe*_*Set 1 concurrency go channels
这是 Go 中的 Concurrency 一书中的代码示例。在 select 块中是以下语句
case takeStream <- <- valueStream:
Run Code Online (Sandbox Code Playgroud)
看不懂双箭头是干什么的,文中也没有解释。当我将其替换为时,输出会发生变化
case takeStream <- valueStream:
Run Code Online (Sandbox Code Playgroud)
所以这显然是必要的
功能齐全:
func take(done<- chan interface{}, valueStream <- chan interface{}, num int) <- chan interface{}{
takeStream := make ( chan interface{})
go func() {
defer close(takeStream)
for i := 0; i < num; i ++ {
select {
case <- done :
return
case takeStream <- <- valueStream:
}
}
}()
return takeStream
}
Run Code Online (Sandbox Code Playgroud)
编辑:如果我理解正确,扩展出来的语句将是
i := 5
valueStream <- i
tmp <- valueStream
takeStream <- tmp
Run Code Online (Sandbox Code Playgroud)
所以
takeStream <- <- valuesStream
Run Code Online (Sandbox Code Playgroud)
是捷径
这解释了为什么当我打电话
fmt.Println(<-takeStream)
Run Code Online (Sandbox Code Playgroud)
我得到了时髦的数字——大概是 valueStream 的一些数字表示
谢谢!
takeStream <- <- valueStream是接收操作(接收操作符)和发送语句的串联。
接收运算符是一元运算符,因此具有最高优先级 ( Spec: Operators ),而 send 语句是一个语句,不属于运算符层次结构。因此,c1 <- <- c2与 相同c1 <- (<-c2)。
所以你的例子是一样的:
takeStream <- (<-valueStream)
Run Code Online (Sandbox Code Playgroud)
(请注意,任何其他解释都没有任何意义。)
和规范:发送语句:
在通信开始之前评估通道和值表达式。
要发送的值必须在发送之前进行评估。因此,您的示例首先从 接收一个值valueStream,然后将该值发送到takeStream...
...或者如果这个发送语句(和接收操作符)独立存在。
当在select语句中用作a的通信操作之一时case,会发生以下情况:
“select”语句的执行分几个步骤:
- 对于语句中的所有情况,接收操作的通道操作数以及发送语句的通道和右侧表达式在进入“选择”语句时按源顺序仅计算一次。结果是一组要接收或发送的通道,以及要发送的相应值。无论选择哪个(如果有)通信操作进行,该评估中的任何副作用都会发生。带有简短变量声明或赋值的 RecvStmt 左侧的表达式尚未计算。
[...]
所以当你有这个时:
select {
case <- done :
return
case takeStream <- <- valueStream:
}
Run Code Online (Sandbox Code Playgroud)
然后<-valueStream进行评估(从 接收值valueStream)。如果操作是阻塞的,那么整个select将阻塞(即使done是关闭的并因此准备好接收)。
一旦从 接收到一个值valueStream,只有到那时才决定是否可以在 上发送该值takeStream,以及case如果其他情况也可以继续进行,是否选择此选项。
- 如果可以进行一个或多个通信,则通过统一伪随机选择选择可以进行的单个通信。否则,如果存在默认情况,则选择该情况。如果没有默认情况,“select”语句会阻塞,直到至少有一个通信可以继续。