github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/blog/content/pipelines/sqdone1.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 is closed or it receives a value
    42  	// from done, then output calls 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  	// ... the rest is unchanged ...
    53  
    54  	wg.Add(len(cs))
    55  	for _, c := range cs {
    56  		go output(c)
    57  	}
    58  
    59  	// Start a goroutine to close out once all the output goroutines are
    60  	// done.  This must start after the wg.Add call.
    61  	go func() {
    62  		wg.Wait()
    63  		close(out)
    64  	}()
    65  	return out
    66  }
    67  
    68  func main() {
    69  	in := gen(2, 3)
    70  
    71  	// Distribute the sq work across two goroutines that both read from in.
    72  	c1 := sq(in)
    73  	c2 := sq(in)
    74  
    75  	// Consume the first value from output.
    76  	done := make(chan struct{}, 2) // HL
    77  	out := merge(done, c1, c2)
    78  	fmt.Println(<-out) // 4 or 9
    79  
    80  	// Tell the remaining senders we're leaving.
    81  	done <- struct{}{} // HL
    82  	done <- struct{}{} // HL
    83  }