Golang缓冲通道在发送之前就已接收数据

我刚接触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是从通道中取出的,甚至没有放入通道中。为什么会这样?


肥皂起泡泡
浏览 248回答 1
1回答

蝴蝶刀刀

没有。将其放在通道上之后Println("PUT into channel")会发生您的情况,这意味着在执行该print语句之前,有机会从通道中读取它。示例输出中的实际执行顺序类似于以下内容:编写器例程写入2通道。读取器例程2从通道接收。读者日常印刷品goroutine: GET &nbsp;2。作家的日常打印&nbsp;PUT into channel 2您对通道的读取和写入以预期的顺序进行,只是您的打印语句使它看起来不正常。如果您将作者的操作顺序更改为:&nbsp;&nbsp;&nbsp;&nbsp;fmt.Println("PUT&nbsp;into&nbsp;channel",&nbsp;j) &nbsp;&nbsp;&nbsp;&nbsp;ch&nbsp;<-&nbsp;j您可能会看到输出更接近您的期望。但是,它不一定完全代表操作顺序,因为:执行是并发的,但对stdout的写入是同步的每个函数调用和通道发送/接收都为调度程序提供了切换的机会,因此即使使用进行运行GOMAXPROCS=1,它也可以在打印和通道操作(在读取器或写入器中)之间切换goroutines。TL; DR:在记录并发操作时,不要过多地阅读日志消息的顺序。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go