Golang 缓冲通道在发送之前接收数据
Posted
技术标签:
【中文标题】Golang 缓冲通道在发送之前接收数据【英文标题】:Golang buffered channel receive data before even sent 【发布时间】:2019-01-17 01:02:41 【问题描述】:我对 golang 很陌生。今天在测试 Golang 中的通道如何工作时,我感到非常困惑。
根据教程:
仅当缓冲区已满时才发送到缓冲通道块。缓冲区为空时接收块。
我的测试程序如下所示:
package main
import "fmt"
func main()
ch := make(chan int, 2)
go func(ch chan int) int
for i := 0; i < 10; i++
fmt.Println("goroutine: GET ", <-ch)
return 1
(ch)
for j := 0; j < 10; j++
ch <- j
fmt.Println("PUT into channel", j)
我得到这样的输出:
PUT into channel 0
PUT into channel 1
goroutine: GET 0
goroutine: GET 1
goroutine: GET 2
PUT into channel 2
PUT into channel 3
PUT into channel 4
PUT into channel 5
goroutine: GET 3
goroutine: GET 4
goroutine: GET 5
goroutine: GET 6
PUT into channel 6
PUT into channel 7
PUT into channel 8
PUT into channel 9
请注意,数字 2 是在放入频道之前从频道中获取的。为什么会这样?
【问题讨论】:
它没有。您的Println("PUT into channel")
发生在您将其放入通道之后,这意味着在执行该语句之前有机会从通道中读取它。 IE。您的读取是从/向通道写入的操作按预期顺序发生,只是您的打印语句似乎出现故障。
您关于发送到缓冲通道的问题与您使用的程序完全不同。
【参考方案1】:
它没有。您的Println("PUT into channel")
发生在您将其放在通道上之后,这意味着在执行该打印语句之前有机会从通道中读取它。
示例输出中的实际执行顺序大致如下:
-
编写器例程将
2
写入通道。
Reader 例程从通道接收2
。
阅读器例程打印goroutine: GET 2
。
编写器例程打印PUT into channel 2
您对通道的读取和写入操作按预期顺序进行,只是您的打印语句使它看起来有问题。
如果您将编写器的操作顺序更改为:
fmt.Println("PUT into channel", j)
ch <- j
您可能会看到输出更接近您的预期。然而,它仍然不一定完全代表操作的顺序,因为:
-
执行是并发的,但对标准输出的写入是同步的
每个函数调用和通道发送/接收都是调度程序切换的机会,因此即使使用
GOMAXPROCS=1
运行,它也可以在打印和通道操作(在读取器或写入器中)之间切换 goroutine。李>
TL;DR:在记录并发操作时不要过多阅读日志消息的顺序。
【讨论】:
以上是关于Golang 缓冲通道在发送之前接收数据的主要内容,如果未能解决你的问题,请参考以下文章