英文:
How do I know close is necessary?
问题
有一些情况下你需要关闭通道,而有些情况下则不必要。
这里是一个需要关闭通道的例子:
queue := make(chan string, 2)
queue <- "one"
queue <- "two"
close(queue)
for elem := range queue {
fmt.Println(elem)
}
在这个例子中,我得到了一个致命错误:所有的goroutine都处于休眠状态 - 死锁!
而这段代码中关闭通道是可选的:
jobs := make(chan int, 5)
done := make(chan bool)
go func() {
for {
j, more := <-jobs
if more {
fmt.Println("received job", j)
} else {
fmt.Println("received all jobs")
done <- true
return
}
}
}()
for j := 1; j <= 3; j++ {
jobs <- j
fmt.Println("sent job", j)
}
close(jobs)
fmt.Println("sent all jobs")
<-done
// close(done)
希望这些对你有帮助!
英文:
There are some cases you need to close channel and some cases that it is not necessary.
http://play.golang.org/p/piJHpZ2-aU
queue := make(chan string, 2)
queue <- "one"
queue <- "two"
close(queue)
for elem := range queue {
fmt.Println(elem)
}
Here I am getting
fatal error: all goroutines are asleep - deadlock!
whereas this code's close is optional
http://play.golang.org/p/Os4T_rq0_B
jobs := make(chan int, 5)
done := make(chan bool)
go func() {
for {
j, more := <-jobs
if more {
fmt.Println("received job", j)
} else {
fmt.Println("received all jobs")
done <- true
return
}
}
}()
for j := 1; j <= 3; j++ {
jobs <- j
fmt.Println("sent job", j)
}
close(jobs)
fmt.Println("sent all jobs")
<-done
// close(done)
答案1
得分: 6
第一个例子中,由于使用了range
关键字,需要关闭通道。当range
与通道一起使用时,它会继续尝试从通道中读取,直到通道关闭。
根据http://golang.org/ref/spec#For_statements的说明:
[使用
range
进行迭代时]...对于通道,产生的迭代值是连续发送到通道的值,直到通道关闭。如果通道为nil,则range表达式将永远阻塞。
这意味着你必须关闭通道才能退出循环。
在第二个例子中,你使用了接收操作符<-
。这个操作符会阻塞,直到可以从通道中取出一个元素。由于通道中有一个等待被传递的元素,它会立即返回。在这种情况下,关闭通道是可选的,因为在此之后没有其他阻塞操作,所以保持通道"开放"也是可以的。
详见通道部分获取更多细节...
英文:
The first example the channel needs to be closed because of the usage of the range
keyword. When range is used with a channel, it will continue to try to read from the channel until the channel is closed.
From http://golang.org/ref/spec#For_statements
> [When using range
for] ...channels, the iteration values produced are the successive values sent on the channel until the channel is closed. If the channel is nil, the range expression blocks forever.
Which means that you have to close the channel to exit the loop.
In the second example you are using the receive operator <-
. This operator will block until one item can be pulled out of the channel. Since there is one item waiting in the channel to be delivered, it will yield immediately. In this case, close is optional because there are no other blocking operations on the channel after that, so it's just as happy to stay "open".
See the channels section for more details...
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论