在 Go 中如何向无缓冲通道写入/读取多个值?

问题描述 投票:0回答:1

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

  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 routine read : 27<br>
main read 1 -: 42<br>
main read 2 -: 9<br>

游乐场链接:https://play.golang.org/p/DYzfYh-kXnC

go goroutine
1个回答
3
投票

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

  1. goroutines 启动后,您的主例程将被阻止从通道读取

    c
    ,因为它还没有看到要读取的值。
    writeToChan
    例程在将第一个值写入通道之前等待一秒钟

  2. goroutine

    rdFrmChan
    也被阻塞,因为它正在等待通道上的读取
    ch

  3. 1秒后,当

    writeToChan
    上的睡眠到期时,第一次写入(
    c <- 42
    )将首先解锁您的主例程,导致该值存储在
    x
    中,即42

  4. 接下来,

    rdFrmChan
    在下一次写入通道时被解除阻塞(
    c <- 27
    )并看到值27。在打印该值后,例程在此时终止

  5. 此时,只有一个要写入的值和一个要读取的值。来自 goroutine 的第三次写入 (

    c <- 9
    ) 允许主例程读取该值作为
    <-ch
    的一部分并打印它

© www.soinside.com 2019 - 2024. All rights reserved.