在Go语言中,向/从一个无缓冲通道中写入/阅读多个值是如何工作的?

guicsvcw  于 2023-09-28  发布在  Go
关注(0)|答案(1)|浏览(123)

这似乎挑战了我对无缓冲通道的理解,即它只能接受一个值,然后它会阻止读取器读取它。
1.在下面的代码中,writeToChan是如何写3个值的?
1.更令人惊讶的是,这些值如何在以后被读取,尽管顺序不同?
摘自https://golang.org/doc/effective_go#channels
接收器总是阻塞,直到有数据要接收。如果通道未缓冲,则发送方阻塞,直到接收方接收到该值。如果通道有缓冲区,则发送方只会阻塞,直到值已被复制到缓冲区;如果缓冲器已满,则这意味着等待,直到某个接收器已经检索到值。

package main

import (
    "fmt"
    "time"
)

func main() {

    ch := make(chan int)

    go writeToChan(ch)
    go rdFrmChan(ch)
    
    x := <- ch
    fmt.Println("main read 1 -:",x)
    fmt.Println("main read 2 -:",<-ch)
}

func writeToChan(c chan int) {
    time.Sleep(time.Second * 1)
    c <- 42
    c <- 27
    c <- 9
}

func rdFrmChan(c chan int) {
    fmt.Println("Go routine read :", <-c)
}

输出量:

Go routine read : 27<br>
main read 1 -: 42<br>
main read 2 -: 9<br>

Playground链接:https://play.golang.org/p/DYzfYh-kXnC

fykwrbwg

fykwrbwg1#

如果您了解事件发生的顺序,则粘贴的摘录的每一行都可以通过示例代码进行验证。
1.在goroutines启动之后,你的主例程被阻塞阅读,因为它还没有看到一个要读取的值。writeToChan例程在将第一个值写入通道之前等待一秒钟

  1. goroutine rdFrmChan也被阻塞,因为它正在等待读取通道ch
  2. 1s后,当writeToChan上的休眠到期时,第一次写入(c <- 42)将首先解除主例程的阻塞,导致值存储在x中,即42
    1.接下来,rdFrmChan在下一次写入通道(c <- 27)时被解除阻塞,并看到值27。打印值后,例程在此时终止
    1.此时,只有一个值要写入,一个值要读取。goroutine的第三次写入(c <- 9)允许主例程读取<-ch的值并打印出来

相关问题