go - channel 在不同的 goroutine 中消费顺序

标签 go

package main

import (
    "fmt"
    "time"
)

func main() {
    done := make(chan bool)

    go func() {
        for {
            select {
            case <-done:
                fmt.Println("here")
            }
        }
    }()

    go func() {
        q := time.NewTimer(time.Second)
        <-q.C
        done <- true
    }()

    <-done
    fmt.Println("closing")
}

我的问题是 done channel 是否由 goroutine 而不是主 goroutine 使用。 该程序将被阻止。

但事实是程序永远不会被阻塞。main goroutine 似乎每次都消耗 done channel 。

为什么?

最佳答案

尽管我没有在文档中找到答案,但看起来接收值是首先尝试从 channel 读取的例程。在我们的例子中,总是 main方法几乎总是达到 <-done (99.0%),因为例程异步启动并需要一段时间才能运行。但无论如何,我强烈建议你不要依赖它,因为这不能保证。

为了演示它,请看下面的例子:

package main

import (
    "fmt"
    "time"
)

func main() {
    done := make(chan bool)

    n := 5

    for i := 0; i < n; i++ {
        go func(i int) {
            fmt.Println(i, "Waiting to read")
            <-done
            fmt.Println(i, "DONE")
        }(i)
        time.Sleep(time.Second)
    }

    time.Sleep(time.Second)

    for i := 0 ; i < n; i++ {
        time.Sleep(time.Second)
        done <- true
    }

    time.Sleep(time.Second)
}

哪个会产生输出

0 Waiting to read
1 Waiting to read
2 Waiting to read
3 Waiting to read
4 Waiting to read
0 DONE
1 DONE
2 DONE
3 DONE
4 DONE

关于go - channel 在不同的 goroutine 中消费顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53426758/

相关文章:

go - 如何从嵌套函数修改 struct boolean?

go - 如何在 Windows 中为 golang 配置 glide(用于 vendor 包)

go - 我已经设置了我的 $GOPATH,但它不起作用

multithreading - Golang sleep 线程而不是忙于等待

go - 如何获取所有定义的类型?

go - 如何让 golang 接口(interface)实现返回另一个接口(interface)的实现?

ubuntu - 如何在 Ubuntu Precise 中安装当前版本的 Go

if-statement - go - 如何使用golang goroutine,select和if语句返回?

Go Lang 工作区重复包名称可执行冲突

go - 模拟系统调用错误