Simulating my real problem I have this code.
Basically, each element of the array "letters" along with its index is sent to a goroutine to compare it with "x", then it sends a response through the channel.
My idea is that it runs on "x" threads, in the real case I use 8 threads.
package main
import (
"strconv"
"sync"
)
var wg sync.WaitGroup
const sizeLetters = 12
func detectX(ch2 chan int, j int, letters [sizeLetters]string) {
if letters[j] == "x" {
ch2 <- j
}else{
ch2 <- -1
}
}
func main() {
ch1 := make(chan int)
ch2 := make(chan int)
letters := [sizeLetters]string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"}
threads:= 4
wg.Add(threads)
for i := 0; i < threads; i++ {
go func() {
for {
j, ok := <-ch1
if !ok {
wg.Done()
}
detectX(ch2, j, letters)
}
}()
}
for i := 0; i < sizeLetters; i++ {
ch1<-i // add i to the queue
}
k, ok := <-ch2 //k contains the position of X, if exist
if !ok {
wg.Done()
}
if k != -1 { //when exist
println("X exist in position: " + strconv.Itoa(k))
}
println("X doesn´t exist")
close(ch2)
close(ch1)
wg.Wait()
}
Insufficient reputation to comment. So, in lieu of a comment, here is an alternate version of the code:
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup
const sizeLetters = 12
func detectX(ch2 chan int, j int, letters [sizeLetters]string) {
if letters[j] == "x" {
ch2 <- j
}
}
func main() {
ch1 := make(chan int)
ch2 := make(chan int)
letters := [sizeLetters]string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"}
threads := 4
wg.Add(threads)
for i := 0; i < threads; i++ {
go func() {
for {
j, ok := <-ch1
if !ok {
wg.Done()
return
}
detectX(ch2, j, letters)
}
}()
}
// Use a goroutine to close ch2. It is only safe to do this
// after all the other goroutines have exited.
go func() {
wg.Wait()
close(ch2)
}()
for i := 0; i < sizeLetters; i++ {
ch1 <- i // add i to the queue
}
close(ch1)
if k, ok := <-ch2; ok && k != -1 { //when exist
fmt.Println("X exist in position:", k)
} else {
fmt.Println("X doesn´t exist")
}
}
It still has some data dependent issues (unless the letters
array is guaranteed to not contain duplicates):
"x"
in the array, the goroutines will not all exit. That is, main()
does not drain ch2
.threads
"x"
values, then the code will deadlock in the top level for
loop in main()
since the writes to ch1
will run out of unblocked goroutines to consume them.
"x"
values are possible in the letters
array, you could make the ch2
channel that deep: ch2 := make(chan int, depth)
. This will allow all the goroutines to exit, but ch2
will potentially still contain undrained data.