douchen4534 2016-10-11 19:48
浏览 47
已采纳

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

I am on the concurrency example here: https://tour.golang.org/concurrency/5

This is the code:

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)
}

There is quite a bit about this that is confusing to me and the tour itself doesn't say much about it. It says that select will wait on communication operations but I don't really get how that applies to the function that it sends to a goroutine before calling fibonacci. fmt.Println is being sent the channel c, but I just don't see why or how this makes any sense...

I have so many questions about this, I am hoping that everything falls into place after understanding the first part...

  • 写回答

1条回答 默认 最新

  • doutongwei4380 2016-10-11 20:02
    关注

    In the code example the goroutine is launched, and runs until it hits fmt.Println(<- c) where it is printing the values it receives from c. At this point in time i == 0 we're in the first iteration. Meanwhile, since this is running in a goroutine, main has continued execution and called fibonacci passing it the c and quit channels. The fibonacci function is sitting in an 'infinite' select, meaning you will never get out of this without explicitly calling return as it does when it receives from the quit channel.

    So back in main, where you invoked the goroutine, it blocks until receiving from the channel, fibonacci begins executing and sending on that channel, providing the next number in the fibonacci sequence until that loop terminates (when i == 10) at which point the code there moves down to quit <- 0 where is sends on the quit channel. Since you're in an infinite select over there in fibonacci it will always execute the next available case, it cannot continue sending on c because that channel is not buffered, it only allows one item and is full, instead it moves in the quit case statement because it has received something on the quit channel, at which point it prints quit and returns.

    Hope that helps. Some of the language may not be 100% accurate. Really just trying to illustrate how this control flow works. I think actually, the select waits until the goroutine in main can receive at which point it goes into the c <- x statement and sends. You can observe this by trying to read an item out of the channel after everything is done, which causes a panic. In effect they're both waiting for one another, you can't send on a full channel and if you just read off it without any other control flow (like a select) then you will block until there is something there to receive.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 使用ue5插件narrative时如何切换关卡也保存叙事任务记录
  • ¥20 软件测试决策法疑问求解答
  • ¥15 win11 23H2删除推荐的项目,支持注册表等
  • ¥15 matlab 用yalmip搭建模型,cplex求解,线性化处理的方法
  • ¥15 qt6.6.3 基于百度云的语音识别 不会改
  • ¥15 关于#目标检测#的问题:大概就是类似后台自动检测某下架商品的库存,在他监测到该商品上架并且可以购买的瞬间点击立即购买下单
  • ¥15 神经网络怎么把隐含层变量融合到损失函数中?
  • ¥15 lingo18勾选global solver求解使用的算法
  • ¥15 全部备份安卓app数据包括密码,可以复制到另一手机上运行
  • ¥20 测距传感器数据手册i2c