I try to write a complex program with parallel goroutines. It is my first program with channels ;) Each goroutine returns an array and, unfortunately, the result is "random". If I run 10 times the program, I have 10 different results :(
This is an over simplification of my program, the results is good (maybe because it is too simple) but when I run it with -race argument, there is 4 data races.
I tried to had a close() function but it did not worked.
May you help me to find the mistake ? Thank you very much in advance !
package main
import "fmt"
import "sync"
import "strconv"
func cat_strings(a int, b string) []string{
var y []string
j := strconv.Itoa(a)
y = append(y, j)
y = append(y, b)
return y
}
func main() {
var slice []string
var wg sync.WaitGroup
var x []string
queue := make(chan []string, 10)
wg.Add(10)
for i := 0; i < 10; i++ {
go func(i int) {
defer wg.Done()
x = cat_strings(i, "var")
queue <- x
}(i)
}
//close(queue)
go func() {
defer wg.Done()
for t := range queue {
slice = append(slice, t...)
}
}()
wg.Wait()
fmt.Println(slice)
}
There's two pieces to this fix, don't share the slices between goroutines, and then range over
queue
synchronously inmain
.There's no reason for the extra
x
slice you're sharing between goroutines. If each goroutine needs another slice, define a new one for each. Sharing a single slice is always going to require extra synchronization.The other race is between the goruoutine appending from
queue
to theslice
slice, and the finalfmt.Println
. There's no reason for those be concurrent since you don't want to print until all values have been read, so finish the for-range loop entirely before printing the final value.