首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >go教程选择语句

go教程选择语句
EN

Stack Overflow用户
提问于 2016-01-21 18:03:41
回答 2查看 5K关注 0票数 17

我正在tour.golang.org上学习这些示例,我遇到了这段代码,我不太明白:

代码语言:javascript
复制
package main
import "fmt"

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

func main() {
    c := make(chan int)
    quit := make(chan int)
    go func() { // when does this get called?
        for i := 0; i < 10; i++ {
            fmt.Println(<-c)
        }
        quit <- 0
    }()
    fibonacci(c, quit)
}

我了解通道如何工作的基本知识,但我不了解上面的select语句是如何工作的。本教程的解释是:

select语句允许一个goroutine等待多个通信操作。select阻塞直到它的一个案例能够运行,然后执行该案例。如果多个情况准备就绪,它会随机选择一个。

但是这些案子是如何执行的呢?据我所知,他们是在说:

案例:将x发送到c频道

案例:退出接收

我想我理解第二个只有在退出有一个值的情况下才执行,这个值稍后在go func()中执行。但是,第一次检查是为了什么?而且,在go func()中,我们显然是在打印c的值,但此时c中不应该包含任何内容?我能想到的唯一解释是go func()在调用fibonacci()之后以某种方式执行。我猜这是一条我也不完全理解的大猩猩,它看起来就像魔法。

如果有人能通过这段代码告诉我它在做什么,我将不胜感激。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-01-21 18:12:57

请记住,通道将被阻塞,因此select语句读取:

代码语言:javascript
复制
select {
case c <- x: // if I can send to c
    // update my variables
    x, y = y, x+y
case <-quit: // If I can receive from quit then I'm supposed to exit
    fmt.Println("quit")
    return
}

default大小写的缺失意味着“如果我不能发送到c,并且我无法从退出中读取,那么在我可以之前阻止它。”

然后,在您的主要过程中,您派生出另一个从c读取以打印结果的函数。

代码语言:javascript
复制
for i:=0; i<10; i++ {
    fmt.Println(<-c)  // read in from c
}
quit <- 0  // send to quit to kill the main process.

这里的关键是记住通道阻塞,您使用的是两个未缓冲的通道。通过使用go派生出第二个函数,您可以从c中消费,这样fibonacci就会继续。

戈鲁丁是所谓的“绿色线”。使用关键字go启动函数调用,将其派生为独立于执行主线的新进程。本质上,main()go func() ...是同时运行的!这一点很重要,因为我们在这段代码中使用了生产者/消费者模式。

fibonacci生成值并将其发送给c,由main生成的匿名goroutine将使用来自c的值并对其进行处理(在本例中,“处理”只意味着打印到屏幕上)。我们不能简单地生成所有的值然后使用它们,因为c会阻塞它们。此外,fibonacci将永远产生更多的值(或者直到整数溢出为止),因此即使您有一个具有无限长缓冲区的神奇通道,它也永远不会到达使用者。

票数 16
EN

Stack Overflow用户

发布于 2016-01-21 18:12:28

你差不多明白了。

在go func()中,我们显然是在打印c的值,但此时c中不应该包含任何内容?我能想到的唯一解释是go func()在调用fibonacci()之后以某种方式执行。我猜这是个戈鲁蒂

是的,go关键字启动一个goroutine,所以func()将与fibonacci(c,退出)同时运行。来自Println中的通道的接收只会阻塞,直到有什么可接收的东西。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34931059

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档