go - What is an elegant way to shut down a chain of goroutines linked by channels? -


i'm go learner. in order better understand care , feeding of channels , goroutines, i'm trying build sieve of eratosthenes set of goroutines connected pipeline channels.

here's have far:

// esieve implements sieve of eratosthenes // series of channels connected // goroutines package main  import "fmt"  func sieve(mine int, inch chan int) {     start := true                        // first-number switch     ouch := make(chan int)               // output channel instance     fmt.printf("%v\n", mine)             // print instance's prime     next := <-inch; next > 0; next = <-inch {  // read input channel         fmt.printf("%v <- %v\n",mine,next)         // (trace)         if (next % mine) > 0 {                     // divisible prime?             if start {                   // no; first number through?                  go sieve(next, ouch)     // first number - create instance                 start = false            // first time done             } else {                     // not first time                 ouch <- next             // pass next instance             }         }     } }  func main() {     lim := 30                     // let's 30     fmt.printf("%v\n", 2)         // treat 2 special case     ouch := make(chan int)        // create first segment of pipe     go sieve(3, ouch)             // create instance '3'     prime := 3; prime < lim; prime += 2 { // generate 3, 5, ...         fmt.printf("send %v\n", prime)        // trace         ouch <- prime                         // send down pipe     } } 

and far goes, works nicely.

however, when finish main loop, main exits before numbers still in pipeline of sieve instances have propagated down end.

what simplest, elegant, or accepted way make main routine wait set of goroutines (about 'knows' of first one) complete?

as title question, killing worker goroutines when don't need them anymore: use done idiom. reads closed channel yield 0 value.

make new channel done. when reads channel succeed, goroutines know should quit. close channel in main when have values need.

check if can read channel done, , exit returning, or read next when that's available. partially replaces assignment next in loop:

select { case <-done: return case next = <- inch: } 

ranging on channel works, since closing channel exits loop.

as reverse, body question, waiting set of goroutines finish:

use sync.waitgroup.

var wg sync.waitgroup wg.add(goroutinecount) 

and when each goroutine finishes:

wg.done() 

or use defer:

defer wg.done() 

to wait of them report done:

wg.wait() 

in example, call wg.add(1) when start new goroutine, before call wg.done() , return. long reach 0 once, wg.wait() works expected, wg.add(1) before wg.done.


Comments

Popular posts from this blog

get url and add instance to a model with prefilled foreign key :django admin -

css - Make div keyboard-scrollable in jQuery Mobile? -

ruby on rails - Seeing duplicate requests handled with Unicorn -