package main import ( "fmt" "math/rand" "sync" "time" ) // fetchService simulates fetching data from an external service. func fetchService(serviceName string, resultChan chan<- string) { defer fmt.Printf("[%s] Service finished. ", serviceName) rand.Seed(time.Now().UnixNano() + int64(len(serviceName))) // Seed for variety fetchTime := time.Duration(rand.Intn(500)+200) * time.Millisecond // 200-700ms time.Sleep(fetchTime) result := fmt.Sprintf("Data from %s (took %s)", serviceName, fetchTime) resultChan <- result } // fanIn aggregates results from multiple input channels into a single output channel. func fanIn(inputChans ...<-chan string) <-chan string { var wg sync.WaitGroup multiplexedChan := make(chan string) multiplex := func(c <-chan string) { defer wg.Done() for i := range c { multiplexedChan <- i } } // Start a goroutine for each input channel to multiplex its output for _, c := range inputChans { wg.Add(1) go multiplex(c) } // Start a goroutine to close the multiplexed channel once all inputs are closed go func() { wg.Wait() close(multiplexedChan) }() return multiplexedChan } func main() { fmt.Println("Starting data fetching from multiple services...") serviceAChan := make(chan string) serviceBChan := make(chan string) serviceCChan := make(chan string) // Start goroutines to fetch data concurrently go fetchService("Service A", serviceAChan) go fetchService("Service B", serviceBChan) go fetchService("Service C", serviceCChan) // Close the individual service channels after they have sent their data // In a real application, you might use context for cancellation instead. go func() { time.Sleep(time.Second) close(serviceAChan) close(serviceBChan) close(serviceCChan) }() // Use fan-in to collect all results into one channel allResults := fanIn(serviceAChan, serviceBChan, serviceCChan) fmt.Println(" --- Collected Results ---") for result := range allResults { fmt.Println(result) } fmt.Println("All service results aggregated.") }