【问题标题】:unbuffered channel - multiple value passing无缓冲通道 - 多值传递
【发布时间】:2020-10-19 01:17:22
【问题描述】:
package main

import (
    "fmt"
)

func main() {
    in := make(chan int, 10)
    out := make(chan int)

    for i := 0; i < 10; i++ {
        in <- i
    }

    close(in)

    go func() {
        for {
            i, ok := <-in
            if !ok {
                close(out)
                break
            }

            out <- i * 2 //THIS LINE
        }
    }()

    for v := range out { // AND HERE
        fmt.Println(v)
    }
}

我对 Go 有点陌生,了解了缓冲通道和非缓冲通道之间的区别,但我不确定这段代码是如何工作的。由于out 通道没有缓冲,它不应该造成死锁吗?我错过了什么?

【问题讨论】:

    标签: go


    【解决方案1】:

    out 通道是无缓冲的,所以如果你在没有另一个 goroutine 等待读取它的情况下写入它,它将阻塞。读取也一样:它将阻塞,直到另一个 goroutine 写入它。因此,goroutine 在写入时阻塞,直到 main 中的 for 循环从中读取。 main goroutine 会从 out 读取直到关闭,所以当 goroutine 最终关闭时,for 循环终止。

    【讨论】:

    • 那么,for 循环“不拍摄通道的快照,它是 length”并循环通过?说“范围”在运行时是动态的,直到通道过时,这是否正确?
    • 频道范围将从该频道读取,直到频道关闭。它会一直阻塞,直到有人写信给它。
    • 是的。在 goroutine 中,当 in 关闭时,它也会关闭。
    【解决方案2】:

    了解它的工作原理:

    in := make(chan int, 10) out := make(chan int)

    您在上面创建了两个频道。 in 被缓冲可以容纳 10 个值。 out 是无缓冲的,只能保存 1 个值

    对于 i := 0;我

    您正在向您的 in 频道添加 10 个值 [0-9]

    关闭(进入)

    您正在关闭in 频道上的写入。请记住阅读in 仍然开放。

    去 func() {

    您正在创建一个 go 例程来读取 in 通道的值。 (最佳实践是将in 传递给函数,但这不是这里的重点。

       for {
           i, ok := <-in
    

    在循环上方,您读取值直到 in 为空(ok 为空时为 false)

           if !ok {
               close(out)
               break
           }
    

    上面你会关闭out,当你从in读完值时会中断。直到下面的行执行。

           out <- i * 2 //THIS LINE
    

    上面你写到频道out 并阻塞这个goroutine,直到它的值被读取。循环将持续 10 次。

    for v := range out { // 在这里 fmt.Println(v) }

    上面,回到主 goroutine,你会从 out 读取值,阻塞并将控制权传递给另一个 goroutine。这一直持续到 for 循环中断并且 out 关闭。

    【讨论】:

      猜你喜欢
      • 2014-01-30
      • 2020-09-03
      • 2018-10-02
      • 2019-03-27
      • 2021-10-13
      • 2018-05-06
      • 2017-09-06
      • 2016-08-30
      • 1970-01-01
      相关资源
      最近更新 更多