如何解决go中的select语句和选定的案例
我有一个代码https://play.golang.org/p/y5FGVfXdzC3,试图理解为什么选择第二种情况而不选择第一种情况。
这里是示例:
package main
import (
"fmt"
"time"
"log"
)
func foo1() string {
log.Println("foo1 evaluated")
return "quick thing"
}
func foo2(c chan string) {
time.Sleep(5 * time.Second)
c <- "sleepy thing"
}
func main() {
c1 := make(chan string)
c2 := make(chan string)
go foo2(c2)
select {
case c1 <- foo1():
fmt.Println("received",<-c1)
case msg := <-c2:
fmt.Println("received",msg)
}
}
2009/11/10 23:00:00 foo1 evaluated
received sleepy thing
Program exited.
我希望第一种情况会“更快”,因为我们已经准备好发送给c1了,但是事实并非如此,因此选择了第二种情况。您能帮我了解这种情况吗?
解决方法
将永远不会选择频道c1
的情况,因为没有从c1
读取goroutine的信息。仅当准备好读取/写入通道时,才会选择该通道。在这种情况下,c2
已准备好从中读取,因为有一个goroutine正在等待对其进行写入。如果您从c1
创建另一个goroutine读数,则c1
和c2
都将准备就绪,并且将选择其中之一。
将显示消息foo1 evaluated
,因为会立即评估大小写(即调用foo1),但是在将值发送到通道之前阻止了大小写。
每the spec(重点是我):
执行“ select”语句的过程分为几个步骤:
- 对于该语句中的所有情况,在输入“ select”语句后,接收源的通道操作数以及send语句的通道和右侧表达式的源顺序将精确评估一次。 / strong>。结果是一组要从中接收或发送到的通道,以及要发送的相应值。 该评估将产生任何副作用,而与选择进行哪个(如果有)通信操作无关。带有简短变量声明或赋值的RecvStmt左侧的表达式尚未评估。
因此,您看到foo1 evaluated
是因为在选择foo1()
之前调用case
。这并不意味着选择了第一种情况-实际上,根据输出,将选择第二种情况,否则将不会打印received sleepy thing
。
无法选择第一种情况,因为c1
的发送和接收在同一个goroutine中(运行select
的那个),并且没有缓冲。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。