How to safely close multiple channels with a single signal channel using sync in Golang?

In Golang, you can use a special closing channel to safely close multiple channels concurrently. Here's an example:

package main import ( "fmt" "sync" ) func main() { // Create a signal channel to close other channels signalChan := make(chan bool) // Create multiple worker channels workerChans := make([]chan int, 5) for i := 0; i < len(workerChans); i++ { workerChans[i] = make(chan int) } // Start worker goroutines for i := 0; i < len(workerChans); i++ { go worker(workerChans[i], signalChan) } // Close all worker channels concurrently go closeChannels(workerChans, signalChan) // Wait for worker goroutines to finish wg := sync.WaitGroup{} wg.Add(len(workerChans)) for i := 0; i < len(workerChans); i++ { go func(ch chan int) { defer wg.Done() for value := range ch { fmt.Println(value) } }(workerChans[i]) } // Wait for all goroutines to finish wg.Wait() } // Worker function that processes values from the channel until it's closed func worker(ch chan int, signalChan <-chan bool) { for { select { case value, ok := <-ch: if !ok { return // Channel closed, worker goroutine is done } // Process value from channel fmt.Println("Processing:", value) case <-signalChan: return // Close signal received, worker goroutine is done } } } // Function to close multiple channels with a single signal channel func closeChannels(chans []chan int, signalChan chan<- bool) { for _, ch := range chans { close(ch) } close(signalChan) }

In the above example, we create a signal channel (signalChan) which will be used to instruct all worker goroutines to stop processing values. We also create multiple worker channels (workerChans), each representing a separate worker goroutine.

To close all the worker channels concurrently, we launch a separate goroutine (closeChannels) that loops through all the channels and closes each one. Finally, we close the signal channel to notify all the worker goroutines that they should stop processing.

We use a sync.WaitGroup to wait for all the worker goroutines to finish processing and print their results.

Note that in the worker function, we use a select statement to listen on both the worker channel and the signal channel. If a value is received on the worker channel, it is processed. If a value is received on the signal channel, the worker goroutine returns and terminates.

This approach ensures graceful shutdown of all worker goroutines and avoids potential data race conditions.