package main import ( "fmt" "time" ) // worker simulates a task that sometimes needs to respond to urgent control signals. func worker(dataCh <-chan string, controlCh <-chan string, done chan<- bool) { for { select { case msg := <-controlCh: // Priority 1: Always check control signals first fmt.Printf("Worker: !!! URGENT Control received: %s !!! ", msg) if msg == "stop" { fmt.Println("Worker: Stopping due to control signal.") done <- true return } case data := <-dataCh: // Priority 2: Process data if no control signal fmt.Printf("Worker: Processing data: %s ", data) time.Sleep(50 * time.Millisecond) // Simulate work case <-time.After(200 * time.Millisecond): // Priority 3: Do something if no messages for a while fmt.Println("Worker: Idle, performing routine check...") } } } func main() { dataChannel := make(chan string) controlChannel := make(chan string) doneChannel := make(chan bool) go worker(dataChannel, controlChannel, doneChannel) // Send some data go func() { for i := 0; i < 5; i++ { dataChannel <- fmt.Sprintf("DataItem-%d", i+1) time.Sleep(70 * time.Millisecond) } }() // Send an urgent control signal later go func() { time.Sleep(300 * time.Millisecond) controlChannel <- "pause" time.Sleep(200 * time.Millisecond) controlChannel <- "status_report" time.Sleep(400 * time.Millisecond) controlChannel <- "stop" // This should cause the worker to exit }() // Wait for the worker to signal completion <-doneChannel fmt.Println("Main: Worker has completed its task.") close(dataChannel) close(controlChannel) close(doneChannel) // Not strictly necessary after receive, but good practice time.Sleep(50 * time.Millisecond) // Give time for goroutines to clean up fmt.Println("Main: Application finished.") }