英文:
Channel buffer taking one more value than expected in Go
问题
我以为在Go语言中,通道默认情况下只能容纳一个值,除非指定了缓冲区大小。我在这里阅读到了这个问题的解答。但是当我运行以下代码时:
func main() {
for i := range numGen(6) {
log.Println("taking from channel", i)
}
}
func numGen(num int) chan int {
c := make(chan string)
go func() {
for i := 0; i < num; i++ {
log.Println("passing to channel", i)
c <- i
}
close(c)
}()
return c
}
我的输出是:
2017/06/13 18:09:08 passing to channel 0
2017/06/13 18:09:08 passing to channel 1
2017/06/13 18:09:08 taking from channel 0
2017/06/13 18:09:08 taking from channel 1
2017/06/13 18:09:08 passing to channel 2
2017/06/13 18:09:08 passing to channel 3
2017/06/13 18:09:08 taking from channel 2
2017/06/13 18:09:08 taking from channel 3
2017/06/13 18:09:08 passing to channel 4
2017/06/13 18:09:08 passing to channel 5
2017/06/13 18:09:08 taking from channel 4
2017/06/13 18:09:08 taking from channel 5
这表明该通道同时容纳了两个值。指定缓冲区大小如下所示:
c := make(chan int, 0)
没有起到任何作用。有没有办法让它只容纳一个值,而不是两个?
英文:
I thought that channels in Go only hold 1 value by default unless the buffer size if specified. I read that <a href="https://stackoverflow.com/questions/11943841/golang-what-is-channel-buffer-size">here</a>. But when I run this:
func main (){
for i := range numGen(6) {
log.Println("taking from channel", i)
}
}
func numGen(num int) chan int {
c := make(chan string)
go func() {
for i := 0; i < num; i++ {
log.Println("passing to channel", i)
c <- i
}
close(c)
}
return c
}
my output is:
2017/06/13 18:09:08 passing to channel 0
2017/06/13 18:09:08 passing to channel 1
2017/06/13 18:09:08 taking from channel 0
2017/06/13 18:09:08 taking from channel 1
2017/06/13 18:09:08 passing to channel 2
2017/06/13 18:09:08 passing to channel 3
2017/06/13 18:09:08 taking from channel 2
2017/06/13 18:09:08 taking from channel 3
2017/06/13 18:09:08 passing to channel 4
2017/06/13 18:09:08 passing to channel 5
2017/06/13 18:09:08 taking from channel 4
2017/06/13 18:09:08 taking from channel 5
which shows that the channel is holding 2 values at a time. Specifying a buffer size like this
c := make(chan int, 0)
does nothing. Any way I could make it only hold 1, value, not 2?
答案1
得分: 3
这是代码的执行过程:
- 主 goroutine 在通道上进行读取并阻塞。
- 第二个 goroutine 写入通道并继续执行。
- 第二个 goroutine 在第二次写入尝试时阻塞,因为没有人在读取。
- 主 goroutine 继续执行,打印读取的数字。
- 主 goroutine 读取另一个数字,因为有人在写入。
- 主 goroutine 打印读取的数字,并在下一次读取时阻塞。
- 第二个 goroutine 在步骤 2 处继续执行。
没有缓冲区,只有并发执行。
英文:
> which shows that the channel is holding 2 values at a time.
Thats not the case. This is how the code executes:
- The main goroutine blocks on a read on the channel
- The second goroutine writes to the channel and continues executing.
- The second goroutine blocks at the second write attempt because noone is reading
- The main goroutine continues executing, prints the read number
- The main goroutine reads another number since someone is writing to it
- The main goroutine prints the read number and blocks on the next read
- The second goroutine continues executing at step 2.
There is no buffer, just concurrency.
答案2
得分: 0
package main
import (
"log"
)
func main() {
seq := make(chan bool)
for i := range numGen(6, seq) {
<-seq
log.Println("从通道中取出", i)
}
}
func numGen(num int, seq chan bool) chan int {
c := make(chan int)
go func() {
for i := 0; i < num; i++ {
c <- i
log.Println("向通道中传递", i)
seq <- true // 为了保证顺序,这里发送一个信号。
}
close(c)
}()
return c
}
这是一个Go语言的代码示例,它创建了一个通道(channel)并使用goroutine来生成一系列数字。在主函数中,通过循环从通道中接收数字,并在接收完后发送一个信号量到另一个通道。在numGen函数中,使用循环将数字发送到通道中,并在发送完后发送一个信号量到seq通道。最后,关闭通道c。
请注意,我只翻译了代码部分,其他内容不做翻译。
英文:
package main
import (
"log"
)
func main() {
seq := make(chan bool)
for i := range numGen(6, seq) {
<-seq
log.Println("taking from channel", i)
}
}
func numGen(num int, seq chan bool) chan int {
c := make(chan int)
go func() {
for i := 0; i < num; i++ {
c <- i
log.Println("passing to channel", i)
seq <- true // 要保证顺序,这里发送一个信号量。
}
close(c)
}()
return c
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论