我尝试在GO中编写一个简单的代码,其中两个go例程(Send和Receive)发送彼此的整数。我给出下面的代码。任何人都可以帮助我为什么这个程序的输出是[无输出]。有什么愚蠢的错误(对不起,我是GO的新手)?
package main
func Send (in1 <-chan int, out1 chan<- int) {
i := 2
out1 <- i
print(i, "\n")
}
func Receive (in <-chan int, out chan<- int) {
i := <-in
print(i, "\n")
out <- i
}
func main() {
for i := 0; i < 10; i++ {
ch1 := make(chan int)
ch := make(chan int)
go Send (ch1 , ch)
go Receive (ch , ch1)
ch = ch1
ch1 = ch
}
}
答案 0 :(得分:2)
这个怎么样:
package main
func Send (ch chan<- int) {
for i := 0; i < 10; i++ {
print(i, " sending\n")
ch <- i
}
}
func Receive (ch <-chan int) {
for i := 0; i < 10; i++ {
print(<-ch, " received\n")
}
}
func main() {
ch := make(chan int)
go Receive(ch)
Send(ch)
}
当我在golang.org上运行它时的输出是:
0 sending
0 received
1 sending
2 sending
1 received
2 received
3 sending
4 sending
3 received
4 received
5 sending
6 sending
5 received
6 received
7 sending
8 sending
7 received
8 received
9 sending
我不确定为什么9从未收到过。应该有一些方法来睡眠主线程,直到接收goroutine完成。此外,接收者和发送者都知道他们将发送10个号码是不优雅的。其中一个goroutines应该在对方完成工作时关闭。我不知道该怎么做。
<强> EDIT1:强>
这是一个具有两个通道的实现,并且go例程在彼此之间来回发送inlet。一个被指定为响应者,它只在收到int后发送和int。响应者只是将两个加到他收到的int中,然后将其发回。
package main
func Commander(commands chan int, responses chan int) {
for i := 0; i < 10; i++ {
print(i, " command\n")
commands <- i
print(<-responses, " response\n");
}
close(commands)
}
func Responder(commands chan int, responses chan int) {
for {
x, open := <-commands
if !open {
return;
}
responses <- x + 2
}
}
func main() {
commands := make(chan int)
responses := make(chan int)
go Commander(commands, responses)
Responder(commands, responses)
}
我在golang.org上运行时的输出是:
0 command
2 response
1 command
3 response
2 command
4 response
3 command
5 response
4 command
6 response
5 command
7 response
6 command
8 response
7 command
9 response
8 command
10 response
9 command
11 response
答案 1 :(得分:2)
David Grayson的修复工作,但是为什么9
并不总是被收到的解释不适合评论!
当发送goroutine在通道上发送值时,它会阻塞,直到接收goroutine接收到它。那时,它已被解锁。 go调度程序几乎可以在它给接收goroutine一个机会打印任何东西之前立即从main返回。如果将GOMAXPROCS设置为大于1的值,则这种情况发生的频率较低,因为接收goroutine在主goroutine处于活动状态时不会阻塞。
如果你想在完成所有goroutine之前停止main返回,你可以从Receive()
返回一个频道,如下所示:
package main
import "fmt"
func Send(ch chan<- int) {
for i := 0; i < 10; i++ {
fmt.Println(i, " sending")
ch <- i
}
close(ch)
}
func Receive(ch <-chan int) (<-chan bool) {
done := make(chan bool)
go func() {
for {
i, ok := <-ch
if !ok {
break
}
fmt.Println(i, " received")
}
done <- true
}()
return done
}
func main() {
ch := make(chan int)
d := Receive(ch)
Send(ch)
_ = <-d
}
至于为什么你的输出在你的原始例子中是空的:你制作两个goroutines,因此main完全解锁,所以它只返回并退出程序!我也确实犯了这个错误,但是运行时只加入主goroutine,而不是像所期望的那样与所有goroutine结合。