package main import ( "fmt" "time" ) // doWorkWithTimeout simulates a task that might take a variable amount of time. // It attempts to send a result on a channel, but respects a timeout. func doWorkWithTimeout(id int, resultCh chan<- string, timeout time.Duration) { fmt.Printf("Worker %d: Started work... ", id) // Simulate work that takes a random duration. sleepTime := time.Duration(id*100 + 200) * time.Millisecond // Vary sleep time based on ID // Make some workers intentionally slow to trigger timeout if id%2 == 0 { sleepTime += 500 * time.Millisecond } time.Sleep(sleepTime) output := fmt.Sprintf("Worker %d: Work finished after %v", id, sleepTime) select { case resultCh <- output: // Try to send the result. fmt.Printf("Worker %d: Result sent successfully. ", id) case <-time.After(timeout): // If sending takes longer than the timeout. fmt.Printf("Worker %d: Timeout while trying to send result. Result was: %q (slept %v) ", id, output, sleepTime) } } // receiveWithTimeout attempts to receive a value from a channel with a timeout. func receiveWithTimeout(id int, inputCh <-chan string, timeout time.Duration) (string, bool) { fmt.Printf("Main: Attempting to receive result for worker %d with timeout %v... ", id, timeout) select { case result := <-inputCh: fmt.Printf("Main: Successfully received result for worker %d: %q ", id, result) return result, true case <-time.After(timeout): fmt.Printf("Main: Timeout while waiting for result from worker %d ", id) return "", false } } func main() { const numWorkers = 5 results := make(chan string, numWorkers) fmt.Println("Starting workers...") for i := 1; i <= numWorkers; i++ { go doWorkWithTimeout(i, results, 300*time.Millisecond) // Worker send timeout } // Give workers some time to start and potentially send results time.Sleep(100 * time.Millisecond) fmt.Println(" --- Main goroutine collecting results ---") for i := 1; i <= numWorkers; i++ { // For demonstration, we'll try to receive with a different timeout for each worker's result. receiveTimeout := 400 * time.Millisecond if i == 2 { // Make one receiver deliberately too fast receiveTimeout = 100 * time.Millisecond } if i == 4 { // Make another receiver very patient receiveTimeout = 1 * time.Second } receiveWithTimeout(i, results, receiveTimeout) } fmt.Println(" Main goroutine finished collecting. Giving workers time to finish logging...") time.Sleep(1 * time.Second) fmt.Println("Exiting.") }