英文:
Why do I receive values from a closed channel?
问题
我正在调查通道的行为,并且对它们的行为感到困惑。规范中说:“在调用close之后,并且在接收到之前发送的所有值之后,接收操作将返回通道类型的零值,而不会阻塞。”然而,即使在那个时候通道已经关闭,我仍然在range语句中获取到值。为什么会这样呢?
package main
import "fmt"
import "sync"
import "time"
func main() {
iCh := make(chan int, 99)
var wg sync.WaitGroup
go func() {
for i := 0; i < 5; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
iCh <- i
}(i)
}
wg.Wait()
close(iCh)
}()
time.Sleep(5 * time.Second)
print("通道现在应该已经关闭了\n")
for i := range iCh {
fmt.Printf("%v\n", i)
}
print("完成")
}
**编辑:**如果我将close
语句移到通道的range之前,它会彻底关闭通道。所以我想知道为什么使用"time.Sleep"的技巧不起作用。到那个时候(5秒),所有的goroutine应该已经完成并且通道已经关闭了,不是吗?
英文:
I'm investigating the channels behaviour and I'm quite confused by their behaviour. The spec say After calling close, and after any previously sent values have been received, receive operations will return the zero value for the channel's type without blocking.
However it seems I still get the values in the range statement even if by that time the channel is closed. Why is that?
package main
import "fmt"
import "sync"
import "time"
func main() {
iCh := make(chan int, 99)
var wg sync.WaitGroup
go func() {
for i := 0; i < 5; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
iCh <- i
}(i)
}
wg.Wait()
close(iCh)
}()
time.Sleep(5 * time.Second)
print("the channel should be closed by now\n")
for i := range iCh {
fmt.Printf("%v\n", i)
}
print("done")
}
Edit: It seems that if I move the close
statement just before the channel range it closes it for good. So I'm wondering why it's not working with the "time.Sleep" trick too . By that time (5 seconds) all the go routines should have been completed and the channel closed, isn't it ?
答案1
得分: 31
《Go编程语言规范》
关闭通道c的内置函数close(c)表示不会再向该通道发送更多的值。
在调用close之后,并在接收到之前发送的任何值之后,接收操作将返回该通道类型的零值,而不会阻塞。
在通道缓冲区中,有5个先前发送的值,然后是一个关闭操作。
例如,
package main
import (
"fmt"
"sync"
"time"
)
func main() {
iCh := make(chan int, 99)
var wg sync.WaitGroup
go func() {
for i := 0; i < 5; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
iCh <- i
}(i)
}
wg.Wait()
close(iCh)
}()
time.Sleep(5 * time.Second)
fmt.Println("先前发送的值数量:", len(iCh))
for i := range iCh {
fmt.Printf("%v\n", i)
}
print("通道现在应该已关闭\n")
print("完成")
}
输出:
先前发送的值数量: 5
0
1
2
3
4
通道现在应该已关闭
完成
英文:
> The Go Programming Language Specification
>
> Close
>
> For a channel c, the built-in function close(c) records that no more
> values will be sent on the channel.
> After calling close, and after any previously sent values have been
> received, receive operations will return the zero value for the
> channel's type without blocking.
In the channel buffer there are 5 previously sent values followed by a close.
For example,
package main
import (
"fmt"
"sync"
"time"
)
func main() {
iCh := make(chan int, 99)
var wg sync.WaitGroup
go func() {
for i := 0; i < 5; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
iCh <- i
}(i)
}
wg.Wait()
close(iCh)
}()
time.Sleep(5 * time.Second)
fmt.Println("previously sent values", len(iCh))
for i := range iCh {
fmt.Printf("%v\n", i)
}
print("the channel should be closed by now\n")
print("done")
}
Output:
previously sent values 5
0
1
2
3
4
the channel should be closed by now
done
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论