返回频道Golang

时间:2015-02-19 09:08:16

标签: go

我尝试使用Go频道并与go blog下面的功能示例混淆:

func gen(nums []int) <-chan int {
    out := make(chan int)
    go func() {
        for _, n := range nums {
            out <- n
        }
        close(out)
    }()
    fmt.Println("return statement is called ")
    return out
}

主要:

func main() {
    c := make(<-chan int)
    c = gen([]int{2, 3, 4, 5})

    // Consume the output.//Print 2,3,4,5
    fmt.Println(<-c)
    fmt.Println(<-c)
    fmt.Println(<-c)
    fmt.Println(<-c)
}

完整代码:http://play.golang.org/p/Qh30wzo4m0

我的怀疑:

  1. 我的理解是,一旦return被调用,函数将被终止,并且该函数内的通道不再有生命。

  2. return语句只调用一次。但是out频道的内容被多次阅读。在这种情况下,实际的执行流程是什么?

  3. (我是并发编程的新手。)

3 个答案:

答案 0 :(得分:9)

out := make(chan int)

这不是缓冲频道,这意味着out <- n阻止,直到有人在某处读取该频道(fmt.Println(<-c)来电) (另见“do golang channels maintain order”)

因此,gen()函数末尾的返回并不意味着文字go func()已终止(因为它仍在等待读者使用out频道的内容)。

  

main功能从out功能返回gen()频道   gen()终止后如何才能获得它?

gen()终止的事实对其返回值(out频道)没有影响:“gen()”的目标是“生成”out信道。

main可以在out终止后很长时间内使用gen()(作为gen()的返回值)。

go func内的文字gen()仍在运行,即使gen()已终止。

答案 1 :(得分:1)

因为gen()会像goroutine一样触发频道填充功能;

go func() {
    for _, n := range nums {
        out <- n
    }
    close(out)
}()

并且当out通道上发送第一个值时它会阻塞,因为尚未接收任何内容(无缓冲通道阻止发送直到收到它们的内容),goroutine 不会在gen()函数返回

来自c

main()的收到
fmt.Println(<-c)
...

然后导致在gen()中启动的goroutine在结果被读出时继续填充通道,然后当goroutine返回时最终返回main(),因为没有任何内容可以发送out 1}},并且c无法接收任何内容。

此外,c := make(<-chan int)中的main()是不必要的,因为gen()会创建一个频道并将其返回。

请参阅Playground

答案 2 :(得分:-1)

我认为这就是您想要的:https://play.golang.org/p/WSBUPPyQiY6

package main

import (
    "fmt"
    "sync"
    "time"
)

func read() (elemChan chan int) {
    elemChan = make(chan int)
    go func() {
        for k := 0; k < 1000; k++ {
            elemChan <- k
        }
        close(elemChan)
    }()
    return
}

func main() {
    fmt.Println("Hello, playground")
    elemChan := read()
    wg := sync.WaitGroup{}
    for k := 0; k < 2; k++ {
        wg.Add(1)
        go func(k int) {
            for {
                e, more := <-elemChan
                if !more {
                    wg.Done()
                    return
                }
                fmt.Printf("goroutine #%d: %d\n", k, e)
                time.Sleep(1000 * time.Nanosecond)
            }
        }(k)
    }
    wg.Wait()
}