Channel of channels

A channel of channels is a special kind of channel variable that works with channels instead of other types of variables. Nevertheless, you still have to declare a data type for a channel of channels. You can define a channel of channels using the chan keyword two times in a row, as shown in the following statement:

c1 := make(chan chan int)
The other types of channels presented in this chapter are far more popular and handy than a channel of channels.

The use of channels of channels is illustrated using the code found in chSquare.go, which will be presented in four parts.

The first part of chSquare.go is as follows:

package main 
 
import ( 
    "fmt" 
    "os" 
    "strconv" 
    "time" 
) 
 
var times int 

The second code portion from chSquare.go is shown in the following Go code:

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

After declaring a regular int channel, you will send that to the channel of channels variable. Then you use a select statement in order to be able to read data from the regular int channel or exit your function using the f signal channel.

Once you read a single value from the c channel, you start a for loop that calculates the sum of all integers from 0 up to the integer value that you just read. Next, you will send the calculated value to the c int channel and you are done.

The third part of chSquare.go contains the following Go code:

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) 

The last statement in the preceding code is where you declare a channel of channels variable named cc, which is the star of the program because everything depends on that variable: the cc variable is passed to the f1() function, and it will be used in the for loop which is coming next.

The remaining Go code of chSquare.go is as follows:

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

The f channel is a signal channel used for ending the goroutine when the real work is finished. The ch := <-cc statement allows you to get a regular channel from the channel of channels variable in order to be able to send an int value to it using ch <- i. After this, you start reading from it using a for loop. Although the f1() function is programmed to send a single value back, you can also read multiple values. Note that each value of i is served by a different goroutine.

The type of a signal channel can be anything you want, including bool, which is used in the preceding code, and struct{}, which will be used in the signal channel in the next section. The main advantage of a struct{} signal channel is that no data can be sent to it, which can save you from bugs and misconceptions.

Executing chSquare.go will generate the following type of output:

$ 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
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.144.170