V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
dushandz
V2EX  ›  Go 编程语言

求教一段 Go 代码

  •  
  •   dushandz · 2017-11-29 12:10:36 +08:00 · 1734 次点击
    这是一个创建于 2311 天前的主题,其中的信息可能已经有所发展或是发生改变。
    package main
    
    import "fmt"
    
    func fibonacci(c, quit chan int) {
        x, y := 1, 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 下的 case c <- x: 中去呢??

    9 条回复    2018-01-10 13:27:46 +08:00
    zhujinliang
        1
    zhujinliang  
       2017-11-29 12:17:07 +08:00 via iPhone
    c <- x 就是向 c 里传递值,那个 select 选择的是:要么 c 可写入,要么 quit 可读出。
    hdczsf
        2
    hdczsf  
       2017-11-29 12:18:09 +08:00
    package main

    import "fmt"

    func fibonacci(c, quit chan int) {
    x, y := 1, 1
    for {
    select { //走到这里会阻塞等待
    case c <- x: //① 这里把 x 传入通道 c,传入之后,②处立刻可以输出
    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) //② 阻塞 直到有数据可以取才执行 ①处把 x 传入通道 c,这里立刻可以输出
    }
    quit <- 0
    }()
    fibonacci(c, quit)

    }
    araraloren
        3
    araraloren  
       2017-11-29 13:25:33 +08:00
    c,quit 都是 chan 的话,我一个没学过 go 的人都知道这操作明显是不同的
    HarrisonZ
        4
    HarrisonZ  
       2017-11-29 14:07:05 +08:00
    case c <- x 这是向 c 传值,只要 c 是可写的就会走到这里
    dushandz
        5
    dushandz  
    OP
       2017-11-29 14:54:42 +08:00
    @hdczsf = =b 哦 好像明白了 那 select 的执行时随机的 保不齐走到 <- quit 发现 为 false ?
    dushandz
        6
    dushandz  
    OP
       2017-11-29 15:07:56 +08:00
    @hdczsf 不好意思 没说明白 我又整理了下思路 是不是这样
    ② 阻塞 阻塞了 新开的 goroutine
    fibonacci 里的 select 阻塞了 原来的 goroutine
    然后发现两个 goroutine 都准备好了
    随机执行了 case 语句 case <-quit: 执行返回 false ? 因为通道里没有数据? case c <- x: 返回了 true
    dushandz
        7
    dushandz  
    OP
       2017-11-29 15:09:37 +08:00
    @hdczsf sorry select 监听到了 channel c 中有接收 所以会运行
    picone
        8
    picone  
       2017-11-29 18:26:51 +08:00
    @dushandz #6
    select 中 case 的发生是随机的,但是得有东西在 quit 中才可以执行到<- quit 啊。

    chan 操作里面 chan <-是塞东西进 chan,没有缓冲或塞满会阻塞。
    <- chan 操作是取出东西, 如果没东西出来的话会阻塞。
    在 select 里面, 会随机执行一个非阻塞的 case
    ehlxr
        9
    ehlxr  
       2018-01-10 13:27:46 +08:00
    @HarrisonZ 正解
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1000 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 22:06 · PVG 06:06 · LAX 15:06 · JFK 18:06
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.