go - 这个 go 并发示例中发生了什么?

标签 go channel goroutine

我在此处查看并发示例:https://tour.golang.org/concurrency/5

这是代码:

package main

import "fmt"

func fibonacci(c, quit chan int) {
    x, y := 0, 1
    for {
        select {
        case c <- x:
            x, y = y, x + y
        case <- quit:
            fmt.Println("quit")
            return
        }
    }
}

func main() {
    c := make(chan int)
    quit := make(chan int)
    go func() {
        for i := 0; i < 10; i++ {
            fmt.Println(<- c)
        }
        quit <- 0
    }()
    fibonacci(c, quit)
}

关于这一点,有很多让我感到困惑的地方,而巡回演出本身并没有说太多。它说 select 将等待通信操作,但我真的不明白它如何应用于它在调用 fibonacci 之前发送到 goroutine 的函数。 fmt.Println 被发送到 channel c,但我只是不明白为什么或如何这有任何意义......

我对此有很多疑问,我希望在理解第一部分后一切都落到实处...

最佳答案

在代码示例中,goroutine 被启动,并一直运行直到它到达 fmt.Println(<- c)。它在哪里打印它从 c 接收到的值.此时时间i == 0我们正处于第一次迭代中。同时,由于这是在 goroutine 中运行,main 继续执行并调用了 fibonacci。将 c 传递给它和 quit channel 。 fibonacci函数位于“无限”选择中,这意味着如果不显式调用 return,您将永远无法摆脱它。就像它从 quit 收到时所做的那样 channel 。

所以回到 main,在你调用 goroutine 的地方,它会阻塞直到从 channel 接收,fibonacci开始在该 channel 上执行和发送,提供 fibonacci 中的下一个数字序列直到该循环终止(当 i == 10 时),此时那里的代码向下移动到 quit <- 0在退出 channel 上发送的位置。由于您在 fibonacci 中处于无限选择状态它总是执行下一个可用的案例,它不能继续发送 c因为该 channel 没有缓冲,它只允许一个项目并且已满,而是在 quit 中移动case 语句,因为它在 quit 上收到了一些东西 channel ,此时它打印 quit并返回。

希望对您有所帮助。有些语言可能不是 100% 准确。真的只是想说明这个控制流是如何工作的。我认为实际上,select 会等到 main 中的 goroutine 可以接收,此时它会进入 c <- x。声明并发送。您可以通过在完成所有操作后尝试从 channel 中读取一个项目来观察这一点,这会导致 panic 。实际上,他们都在等待彼此,你不能在一个完整的 channel 上发送,如果你只是在没有任何其他控制流(如选择)的情况下读取它,那么你将阻塞直到有东西可以接收。

关于go - 这个 go 并发示例中发生了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39985524/

相关文章:

MySQL - 选择与表中日期最接近的记录并连接到主数据集

go - 为什么 goroutine 的竞争条件不会在某个时候发生?

select - golang : goroute with select doesn't stop unless I added a fmt. 打印()

go - 在 Go 中将 varName 变暗为 int64?

go - 访问没有 http.Request 的上下文

go - 如何使用 goroutines 接收数据并发回信号

go - Go 中的 len(channel) 是线程安全的吗?

go - 为什么使用goroutine channel ?

debugging - Ubuntu下IntelliJ IDEA go-lang-idea-plugin Alpha调试

go - 无法导入 Imagick 包