这是一个例子:
func main() {
c := make(chan int)
i := 0
go goroutine(c)
c <- i
time.Sleep(10 * time.Second)
}
func goroutine(c chan int) {
for {
num := <- c
fmt.Println(num)
num++
time.Sleep(1 * time.Second)
c <- num
}
}
我想在 goroutine 内部做的是从 channel 接收数字,打印它,递增并在一秒钟后将它发送回 channel 。在此之后我想重复这个 Action 。
但结果,操作只做了一次。
输出:
0
我做错了什么吗?
最佳答案
默认情况下,goroutine 通信是同步
和无缓冲
:在接收方接受值之前发送不会完成。必须有一个接收方准备好从 channel 接收数据,然后发送方可以将数据直接交给接收方。
所以 channel 发送/接收操作阻塞,直到另一端准备好:
1. channel 上的发送操作会阻塞,直到接收方可用于同一 channel :如果 ch
上的值没有接收方,则没有其他值可以放在 channel 里。反之亦然:当 channel 不为空时,不能在 ch
中发送新值!因此发送操作将等到 ch
再次可用。
2. channel 的接收操作阻塞,直到发送方可用于同一 channel :如果 channel 中没有值,则接收方阻塞。
下面的例子说明了这一点:
package main
import "fmt"
func main() {
ch1 := make(chan int)
go pump(ch1) // pump hangs
fmt.Println(<-ch1) // prints only 0
}
func pump(ch chan int) {
for i:= 0; ; i++ {
ch <- i
}
}
因为没有接收者,goroutine 挂起并只打印第一个数字。
为了解决这个问题,我们需要定义一个新的 goroutine,它在无限循环中从 channel 中读取数据。
func receive(ch chan int) {
for {
fmt.Println(<- ch)
}
}
然后在 main()
中:
func main() {
ch := make(chan int)
go pump(ch)
go receive(ch)
}
关于go - 如何在同一循环内向 channel 发送值或从 channel 接收值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34760364/