首页 > 解决方案 > 在 Go 中如何向无缓冲通道写入/读取多个值?

问题描述

这似乎挑战了我对无缓冲通道的理解,即它只能取一个值,然后它会阻止读者阅读它。

  1. 如何在以下代码writeToChan中写入 3 个值?
  2. 更令人惊讶的是,这些值如何在以后读取,尽管顺序不同?

摘自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 例程读取:27
主读取 1 -:42
主读取 2 -:9


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

标签: gogoroutine

解决方案


如果您了解事件发生的顺序,则粘贴的每一行摘录都由您的示例代码证明。

  1. 在 goroutines 启动后,你的 main 例程被阻止从 channel 读取c,因为它还没有看到要读取的值。该writeToChan例程在将第一个值写入通道之前等待一秒钟

  2. goroutinerdFrmChan也被阻塞了,因为它在 channel 上等待读取ch

  3. 1s后,当sleep onwriteToChan过期时,第一次write( c <- 42)会先解锁你的主程序,导致值存入xie 42

  4. 接下来,rdFrmChan在下一次写入通道c <- 27

  5. 此时,只有要写入的值和要读取的值。goroutine 中的第三个 write ( c <- 9) 允许主例程读取值作为其一部分<-ch并打印它


推荐阅读