阅读频道的不同方式
Difference Ways to Read Channels
我很好奇为什么从通道读取值的不同方式会导致不同的行为。提供代码:
mychan := make(chan int)
go func() {
i := 0
for {
mychan <- i
<-time.After(time.Second * 1)
i++
}
}()
goroutine "streams" 一个无限的整数序列到一个 mychan
通道。在这段代码之后,如果你像这样直接用 <-mychan
读取:
fmt.Println(<-mychan)
这会按预期打印“0”。如果你继续重复,它会继续阅读:
fmt.Println(<-mychan) // 1
fmt.Println(<-mychan) // 2
//...
但是,使用循环机制,它会无限阻塞。
for i := range mychan {
fmt.Println(i)
}
也就是说这个机制只能从一个关闭的通道中读取,对吧?
然而,使用 select
方法,事情变得更加复杂:
for i:=0; i<=10;i++ {
select {
case <-mychan:
fmt.Println(<-mychan)
}
}
现在它交替打印,例如 1、3、5、9,... 每 2 秒就好像 select
在 mychan
和其他一些不可见通道之间切换一样。添加另一个 case
就可以了(没有双关语意):
for i:=0; i<=10;i++ {
select {
case <-time.After(1 * time.Second):
fmt.Println("foo")
case <-mychan:
fmt.Println(<-mychan)
}
}
// now prints 1, foo, 3, foo, 5, foo, ... every 1s
对于你们中的一些人来说,这个问题似乎微不足道,如果有人能解释和启发我,我将不胜感激。
来自
的行为
for i := range mychan {
fmt.Println(i)
}
似乎是 go playground 上的 运行ning 示例的结果当我 运行 本地代码时,程序无限期地每秒打印一个值。如果他们在服务器上使用一些代码分析工具来确定代码是否会 运行 永远,那就太好了。
正如 Volker 指出的那样,您的第二个示例是每个打印语句读取频道两次。您可以使用
解决此问题
for i:=0; i<=10;i++ {
select {
case <-time.After(1 * time.Second):
fmt.Println("foo")
case x, open := <-mychan:
if !open { return }
fmt.Println(x)
}
}
我很好奇为什么从通道读取值的不同方式会导致不同的行为。提供代码:
mychan := make(chan int)
go func() {
i := 0
for {
mychan <- i
<-time.After(time.Second * 1)
i++
}
}()
goroutine "streams" 一个无限的整数序列到一个 mychan
通道。在这段代码之后,如果你像这样直接用 <-mychan
读取:
fmt.Println(<-mychan)
这会按预期打印“0”。如果你继续重复,它会继续阅读:
fmt.Println(<-mychan) // 1
fmt.Println(<-mychan) // 2
//...
但是,使用循环机制,它会无限阻塞。
for i := range mychan {
fmt.Println(i)
}
也就是说这个机制只能从一个关闭的通道中读取,对吧?
然而,使用 select
方法,事情变得更加复杂:
for i:=0; i<=10;i++ {
select {
case <-mychan:
fmt.Println(<-mychan)
}
}
现在它交替打印,例如 1、3、5、9,... 每 2 秒就好像 select
在 mychan
和其他一些不可见通道之间切换一样。添加另一个 case
就可以了(没有双关语意):
for i:=0; i<=10;i++ {
select {
case <-time.After(1 * time.Second):
fmt.Println("foo")
case <-mychan:
fmt.Println(<-mychan)
}
}
// now prints 1, foo, 3, foo, 5, foo, ... every 1s
对于你们中的一些人来说,这个问题似乎微不足道,如果有人能解释和启发我,我将不胜感激。
来自
的行为for i := range mychan {
fmt.Println(i)
}
似乎是 go playground 上的 运行ning 示例的结果当我 运行 本地代码时,程序无限期地每秒打印一个值。如果他们在服务器上使用一些代码分析工具来确定代码是否会 运行 永远,那就太好了。
正如 Volker 指出的那样,您的第二个示例是每个打印语句读取频道两次。您可以使用
解决此问题for i:=0; i<=10;i++ {
select {
case <-time.After(1 * time.Second):
fmt.Println("foo")
case x, open := <-mychan:
if !open { return }
fmt.Println(x)
}
}