我正在学习Go,现在我正在使用频道。我用频道编写了一个简单的程序。我创建了两个通道,并将通道传递给一个同时调用的函数。
我的期望是从两个频道打印输出,但实际上只打印一个频道输出:
package main
import "fmt"
func square(dat int, ch chan<- int) {
ch <- dat * dat
}
func main() {
resp1 := make(chan int)
resp2 := make(chan int)
go square(20, resp1)
go square(10, resp2)
select {
case msg1 := <-resp1:
fmt.Println(msg1)
case msg2 := <-resp2:
fmt.Println(msg2)
}
}
在每次执行期间打印来自resp1
的消息或来自resp2
的消息。通道应该阻塞,直到某些东西被推入其中,对吧?
答案 0 :(得分:2)
您希望select
同时选择两者吗?这与它的目的正好相反。来自Go Spec:
“select”语句选择一组可能的发送或接收操作中的哪一个将继续。
如果一个或多个通信可以继续进行,则可以通过统一的伪随机选择来选择可以继续进行的单个通信。
如果你想从两个频道中读取,而不是让select
弄清楚哪一个可以被读取(或者如果两者都可以从中读取,则选择一个伪随机),不要使用{ {1}}。请阅读以下两篇文章:
select
<强>更新强>
如果正如@peterSO建议的那样,你的目标是从两个频道开始阅读,从最先准备好的那个开始,我认为这样的事情是合理的方法:
msg1 := <-resp1:
fmt.Println(msg1)
msg2 := <-resp2:
fmt.Println(msg2)
你当然可以将循环硬编码为仅运行两次,但我厌恶这些东西,尽管在这个简单的例子中它并不重要。
答案 1 :(得分:1)
The Go Programming Language Specification
A&#34;选择&#34;声明选择一组可能的发送或 接收操作将继续。
选择选择其中一个。例如,
package main
import "fmt"
func square(dat int, ch chan<- int) {
ch <- dat * dat
}
func main() {
resp1 := make(chan int)
resp2 := make(chan int)
go square(20, resp1)
go square(10, resp2)
// Choose one
select {
case msg1 := <-resp1:
fmt.Println(msg1)
case msg2 := <-resp2:
fmt.Println(msg2)
}
// Choose the other
select {
case msg1 := <-resp1:
fmt.Println(msg1)
case msg2 := <-resp2:
fmt.Println(msg2)
}
}
游乐场:https://play.golang.org/p/TiThqcXDa6o
输出:
100
400
答案 2 :(得分:0)
根据你的代码在select中,只要任何情况匹配将执行并且main函数将终止。这就是为什么它只打印单个通道值。 你可以通过这样做来解决这个问题:
package main
import (
"fmt"
"os"
"time"
)
func square(dat int, ch chan<- int) {
ch <- dat * dat
}
func main() {
resp1 := make(chan int)
resp2 := make(chan int)
go square(20, resp1)
go square(10, resp2)
time.Sleep(1 * time.Second)
for {
select {
case msg1 := <-resp1:
fmt.Println(msg1)
case msg2 := <-resp2:
fmt.Println(msg2)
default:
close(resp1)
close(resp2)
fmt.Println("no value recieved")
os.Exit(0)
}
}
}
输出
100
400
no value recieved
答案 3 :(得分:0)
选择的工作更像是其他语言的交换机(例如:Java),您需要根据需要执行该部分N次。