Here's a full example, including channel cleanup. After all the consumers and producers are finished, the Manager prints out the result (for which I've used a map rather than a slice, since I think it makes the code a tad easier).
package main
import "fmt"
// Consume processes the numbers in ns, sending them on ch after they're
// processed. When the routine is finished, it signals that on done.
func Consume(done chan bool, ch chan int, ns []int) {
for i := range ns {
ch <- i
}
done <- true
}
// Produce "creates" the numbers in ns, sending them on ch after they're
// produced. When the routine is finished, it signals that on done.
func Produce(done chan bool, ch chan int, ns []int) {
for i := range ns {
ch <- i
}
done <- true
}
// Manage creates consumers and producers for the given int slices.
// It returns once all consumers and producers are finished.
func Manage(cons, pros [][]int) {
cch := make(chan int)
pch := make(chan int)
dch := make(chan bool)
n := len(cons) + len(pros)
data := make(map[int]int)
for _, c := range cons {
go Consume(dch, cch, c)
}
for _, p := range pros {
go Produce(dch, pch, p)
}
for n > 0 {
select {
case c := <-cch:
data[c] -= 1
case c := <-pch:
data[c] += 1
case <-dch:
n -= 1
}
}
close(cch)
close(pch)
close(dch)
fmt.Println(data)
}
func main() {
cons := [][]int{{1, 3, 5}, {0, 1, 5}}
pros := [][]int{{0, 1, 1}, {3, 5, 5, 7}}
Manage(cons, pros)
}