github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/blog/content/pipelines/sqdone2.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, len(nums))
    13  	for _, n := range nums {
    14  		out <- n
    15  	}
    16  	close(out)
    17  	return out
    18  }
    19  
    20  // sq receives values from in, squares them, and sends them on the returned
    21  // channel, until in is closed.  Then sq closes the returned channel.
    22  func sq(in <-chan int) <-chan int {
    23  	out := make(chan int)
    24  	go func() {
    25  		for n := range in {
    26  			out <- n * n
    27  		}
    28  		close(out)
    29  	}()
    30  	return out
    31  }
    32  
    33  // merge receives values from each input channel and sends them on the returned
    34  // channel.  merge closes the returned channel after all the input values have
    35  // been sent.
    36  func merge(done <-chan struct{}, cs ...<-chan int) <-chan int {
    37  	var wg sync.WaitGroup
    38  	out := make(chan int)
    39  
    40  	// Start an output goroutine for each input channel in cs.  output
    41  	// copies values from c to out until c or done is closed, then calls
    42  	// wg.Done.
    43  	output := func(c <-chan int) {
    44  		for n := range c {
    45  			select {
    46  			case out <- n:
    47  			case <-done: // HL
    48  			}
    49  		}
    50  		wg.Done()
    51  	}
    52  	wg.Add(len(cs))
    53  	for _, c := range cs {
    54  		go output(c)
    55  	}
    56  
    57  	// Start a goroutine to close out once all the output goroutines are
    58  	// done.  This must start after the wg.Add call.
    59  	go func() {
    60  		wg.Wait()
    61  		close(out)
    62  	}()
    63  	return out
    64  }
    65  
    66  func main() {
    67  	in := gen(2, 3)
    68  
    69  	// Distribute the sq work across two goroutines that both read from in.
    70  	c1 := sq(in)
    71  	c2 := sq(in)
    72  
    73  	// Consume the first value from output.
    74  	done := make(chan struct{}) // HL
    75  	out := merge(done, c1, c2)  // HL
    76  	fmt.Println(<-out)          // 4 or 9
    77  
    78  	// Tell the remaining senders we're leaving.
    79  	close(done) // HL
    80  }