Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
111 lines (87 sloc) 3.15 KB

传送channel的通道

传送channel的通道 是一种特殊的通道变量,它与通道工作而不是其他类型的变量。不过,您仍然要给一个传送 channel 的通道声明一个数据类型。您可以在一行使用 chan 关键字两次定义一个传送 channel 的通道,如下所示:

c1 := make(chan chan int)

这章介绍的其他类型的通道都比传递channel的通道要简单方便。

chSquare.go 代码来说明传递channel的通道的使用,分为四个部分来介绍。

chSquare.go 的第一部分如下:

package main

import (
    "fmt"
    "os"
    "strconv"
    "time"
)

var times int

chSquare.go 的第二段代码如下:

func f1(cc chan chan int, f chan bool) {
    c := make(chan int)
    cc <- c
    defer close(c)

    sum := 0
    select {
        case x := <-c:
            for i := 0; i <= x;  i++ {
                sum = sum + i
            }
            c <- sum
        case <-f:
            return
    }
}

声明一个常规的 int 通道,您把它发送给传递通道的通道变量。然后您使用 select 表达式从常规的 int 通道读取数据和使用 f 信号通道来退出函数。

一旦您从 c 通道读取了信号值,便开始了一个 for 循环来计算从 0 到信号值的所有整数之和。接下来,您发送这个计算值给 c int 通道,执行结束。

chSquare.go 的第三部分如下:

func main() {
    arguments := os.Args
    if len(arguments) != 2 {
        fmt.Println("Need just one integer argument!")
        return
    }

    times, err := strconv.Atoi(arguments[1])
    if err != nil {
        fmt.Println(err)
        return
    }

    cc := make(chan chan int)

上面代理里的最后一句表达式声明了一个名为 cc 的传递通道的通道变量,它是这个程序的开始,因为一切都依赖与它:cc 变量传递给 f1() 函数,并被接下来的 for 循环中使用。

chSquare.go 的其他代码如下:

    for i := 1; i < times + 1; i++ {
        f := make(chan bool)
        go f1(cc, f)
        ch := <-cc
        ch <- i
        for sum := range ch {
            fmt.Print("Sum(", i, ")=", sum)
        }
        fmt.Println()
        time.Sleep(time.Second)
        close(f)
    }
}

f 通道是一个信号通道,用来当真正的工作完成时结束 goroutine。ch := <-cc 表达式允许您从传递通道的通道获得一个常规的通道,使用 ch <-i 发送一个 int 值给它。之后,您使用 for 循环从它读取数据。尽管 f1() 函数编写为发送一个值回来,但您也可以读取多个值。注意 i 的每个值都被不同的 goroutine 执行。

信号通道的类型可以是任何您想要的类型,包括上面用到的 bool 和下节要用到的 struct{} 类型的信号通道。一个 struct{} 信号通道的优点是不能发送数据给它,这能减少错误和错误的想法。

执行 chSquare.go 将产生如下输出:

$go run chSquare.go 4
Sum(1)=1
Sum(2)=3
Sum(3)=6
Sum(4)=10
$go run chSquare.go 6
Sum(1)=1
Sum(2)=3
Sum(3)=6
Sum(4)=10
Sum(5)=15
Sum(6)=21
You can’t perform that action at this time.