github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/blog/content/pipelines/sqfan.go (about)

     1  // +build OMIT
     2  
     3  package main
     4  
     5  import (
     6  	"fmt"
     7  	"sync"
     8  )
     9  
    10  // gen sends the values in nums on the returned channel, then closes it.
    11  func gen(nums ...int) <-chan int {
    12  	out := make(chan int)
    13  	go func() {
    14  		for _, n := range nums {
    15  			out <- n
    16  		}
    17  		close(out)
    18  	}()
    19  	return out
    20  }
    21  
    22  // sq receives values from in, squares them, and sends them on the returned
    23  // channel, until in is closed.  Then sq closes the returned channel.
    24  func sq(in <-chan int) <-chan int {
    25  	out := make(chan int)
    26  	go func() {
    27  		for n := range in {
    28  			out <- n * n
    29  		}
    30  		close(out)
    31  	}()
    32  	return out
    33  }
    34  
    35  // merge receives values from each input channel and sends them on the returned
    36  // channel.  merge closes the returned channel after all the input values have
    37  // been sent.
    38  func merge(cs ...<-chan int) <-chan int {
    39  	var wg sync.WaitGroup // HL
    40  	out := make(chan int)
    41  
    42  	// Start an output goroutine for each input channel in cs.  output
    43  	// copies values from c to out until c is closed, then calls wg.Done.
    44  	output := func(c <-chan int) {
    45  		for n := range c {
    46  			out <- n
    47  		}
    48  		wg.Done() // HL
    49  	}
    50  	wg.Add(len(cs)) // HL
    51  	for _, c := range cs {
    52  		go output(c)
    53  	}
    54  
    55  	// Start a goroutine to close out once all the output goroutines are
    56  	// done.  This must start after the wg.Add call.
    57  	go func() {
    58  		wg.Wait() // HL
    59  		close(out)
    60  	}()
    61  	return out
    62  }
    63  
    64  func main() {
    65  	in := gen(2, 3)
    66  
    67  	// Distribute the sq work across two goroutines that both read from in.
    68  	c1 := sq(in)
    69  	c2 := sq(in)
    70  
    71  	// Consume the merged output from c1 and c2.
    72  	for n := range merge(c1, c2) {
    73  		fmt.Println(n) // 4 then 9, or 9 then 4
    74  	}
    75  }