Reputation: 1637
I was learning goroutines, and was comparing two slices to each other in two goroutines, which is in an infinite loop to compare it forever, which may not be the best example to use, and I couldn't figure out why it is hung.
for ;; {
var wg sync.WaitGroup
wg.Add(2)
go FindinFirst(&Arr1, &Arr2, AddChan, &wg)
go FindinSecond(&Arr2, &Arr1, DelChan, &wg)
counter := 0
for ; ; {
select {
case Add, ok := <- AddChan:
if ok == true {
for k, v := range Add {
fmt.Println(k, ":", v)
}
}else {
counter += 1
}
case Del, ok := <- DelChan:
if ok == true {
for k, v := range Del {
fmt.Println(k, ":", v)
}
}else {
counter += 1
}
}
if counter == 2{
break
}
wg.Wait()
}
Function FindinFirst is
func FindinFirst(Arr1, Arr2 *[]string, AddChan chan string, wg *sync.WaitGroup){
defer wg.Done()
fmt.Println("Starting FindinFirst")
defer close(AddChan)
for _, i := range *Arr1 {
if IfExists(i, *Arr2) {
fmt.Println("Exists")
continue
} else {
AddChan <- i
}
}
}
Function FindinSecond is
func FindinSecond(Arr2, Arr1 *[]string, DelChan chan string, wg *sync.WaitGroup){
defer wg.Done()
fmt.Println("Starting FindinSecond")
defer close(DelChan)
for _, i := range *Arr2 {
if IfExists(i, *Arr1) {
fmt.Println("Exists")
continue
} else {
DelChan <- i
}
}
}
And IfExists
is just a function which return a bool if the value exists in the slice.
However, the routine is stuck with just one value that is being printed, and I am not sure why it is happening. Both the slices has close to 1000 values, and both has uniques. What is wrong with the code?
Upvotes: 0
Views: 93
Reputation: 2443
I don't think there is any use of using wait groups here... Since you are consuming the channels inside a for loop, putting wg.wait()
will block untill all the wait groups are completed.
In this cases, putting a value into AddChan will block unless some one is waiting for it. The code works just for first case, after which it hangs.
You can remove the wg.wait()
and outer for loop and it will work.
func main() {
Arr1 := []string{"a", "b", "c", "d"}
Arr2 := []string{"c", "e", "f", "g"}
AddChan := make(chan string)
DelChan := make(chan string)
var wg sync.WaitGroup
wg.Add(2)
go FindinFirst(&Arr1, &Arr2, AddChan, &wg)
go FindinSecond(&Arr2, &Arr1, DelChan, &wg)
counter := 0
for {
select {
case Add, ok := <-AddChan:
if ok == true {
fmt.Println(Add)
} else {
counter += 1
}
case Del, ok := <-DelChan:
if ok == true {
fmt.Println(Del)
} else {
counter += 1
}
}
//if both the channels are closed, we are good, hence exit
if counter == 2 {
break
}
}
}
Upvotes: 2