Go goroutine with channel strange result -


when run goroutines, 40 value, know concurrency why last number coming? suppose output must be:

page number:  34   page number:  12   page number:  8   page number:  2   page number:  29 

example source code:

package main  import (     "fmt"     "io/ioutil"     "net/http" )  func getwebpagecontent(url string, c chan int, val int) interface{} {      if r, err := http.get(url); err == nil {         defer r.body.close()         if body, err := ioutil.readall(r.body); err == nil {             c <- val             return string(body)         }     } else {         fmt.println(err)     }     return "xox"  }  const max_th = 40  func main() {      // pln := fmt.println     messages := make(chan int)     j := 0; j < max_th; j++ {         go func() { getwebpagecontent("http://www.example.com", messages, j) }()     }      routine_count := 0     var page_number int     {         page_number = <-messages         routine_count++         fmt.println("page number: ", page_number)         if routine_count == max_th {             break         }     }     close(messages) } 

the go programming language

frequently asked questions (faq)

what happens closures running goroutines?

some confusion may arise when using closures concurrency. consider following program:

func main() {     done := make(chan bool)      values := []string{"a", "b", "c"}     _, v := range values {         go func() {             fmt.println(v)             done <- true         }()     }      // wait goroutines complete before exiting     _ = range values {         <-done     } } 

one might mistakenly expect see a, b, c output. you'll see instead c, c, c. because each iteration of loop uses same instance of variable v, each closure shares single variable. when closure runs, prints value of v @ time fmt.println executed, v may have been modified since goroutine launched. detect , other problems before happen, run go vet.

to bind current value of v each closure launched, 1 must modify inner loop create new variable each iteration. 1 way pass variable argument closure:

for _, v := range values {     go func(u string) {         fmt.println(u)         done <- true     }(v) } 

in example, value of v passed argument anonymous function. value accessible inside function variable u.

even easier create new variable, using declaration style may seem odd works fine in go:

for _, v := range values {     v := v // create new 'v'.     go func() {         fmt.println(v)         done <- true     }() } 

therefore, in case, create new variable adding statement j := j,

for j := 0; j < max_th; j++ {     j := j     go func() { getwebpagecontent("http://www.example.com", messages, j) }() } 

for example,

package main  import (     "fmt"     "io/ioutil"     "net/http" )  func getwebpagecontent(url string, c chan int, val int) interface{} {     if r, err := http.get(url); err == nil {         defer r.body.close()         if body, err := ioutil.readall(r.body); err == nil {             c <- val             return string(body)         }     } else {         fmt.println(err)     }     return "xox" }  const max_th = 40  func main() {      // pln := fmt.println     messages := make(chan int)     j := 0; j < max_th; j++ {         j := j         go func() { getwebpagecontent("http://www.example.com", messages, j) }()     }      routine_count := 0     var page_number int     {         page_number = <-messages         routine_count++         fmt.println("page number: ", page_number)         if routine_count == max_th {             break         }     }     close(messages) } 

output:

page number:  23 page number:  6 page number:  1 page number:  3 page number:  28 page number:  32 page number:  18 page number:  22 page number:  0 page number:  36 page number:  7 page number:  21 page number:  12 page number:  2 page number:  5 page number:  4 page number:  33 page number:  13 page number:  20 page number:  27 page number:  29 page number:  8 page number:  31 page number:  10 page number:  17 page number:  25 page number:  19 page number:  35 page number:  14 page number:  38 page number:  15 page number:  30 page number:  37 page number:  39 page number:  26 page number:  9 page number:  16 page number:  11 page number:  24 page number:  34 

Comments

Popular posts from this blog

javascript - jQuery: Add class depending on URL in the best way -

caching - How to check if a url path exists in the service worker cache -

Redirect to a HTTPS version using .htaccess -