以下代码保持打印0.
package main
import (
"fmt"
)
func main() {
c := make(chan int)
go func() {
for i := 0; i < 10; i++ {
c <- i // INPUT
}
close(c)
}()
for {
fmt.Print(<-c) // RECEIVER; OUTPUT
}
}
Run Code Online (Sandbox Code Playgroud)
从我的理解,它应该打印0到9然后继续无限循环.为什么要继续印刷zero?
icz*_*cza 12
你的理解(几乎)是正确的,除了主goroutine中的无限循环不会阻挡但是会无情地接收和打印.
您开始的goroutine会在通道上发送数字0,1,... 9,然后将其关闭.并且从封闭信道接收不会阻塞,相反,它可以立即进行,并且它产生信道的元素类型的零值,这是0该类型的int.这在规范:接收运营商中说明:
所以你确切地知道你应该做什么.首先它打印数字0..9,然后保持打印0速度非常快(没有任何延迟),所以可能你甚至没有注意到初始0..9数字.
略微修改您的示例,以便在15次迭代后退出主goroutine中的循环将立即显示发生的情况:
c := make(chan int)
go func() {
for i := 0; i < 10; i++ {
c <- i // INPUT
}
close(c)
}()
for i := 0; i < 15; i++ {
fmt.Print(<-c) // RECEIVER; OUTPUT
}
Run Code Online (Sandbox Code Playgroud)
输出(在Go Playground上试试):
012345678900000
Run Code Online (Sandbox Code Playgroud)
如果您的目标是在处理(打印)所有已发送的号码后退出,请使用for range频道上的:
for i := range c {
fmt.Print(i) // RECEIVER; OUTPUT
}
Run Code Online (Sandbox Code Playgroud)
如果您的目标是在处理完这10个号码后阻止新号码可用,则不要关闭该频道.这样下一个接收操作就会阻塞.在这种情况下,原始循环和for range循环都可以工作,但for range更好,因为如果/当通道关闭时总是退出.
查看此问题并记住通道公理:非初始化通道的行为如何?