Implementing the Fan-In Pattern in Go
The Fan-In pattern is a design pattern where multiple input streams are merged into a single output stream. This is useful in scenarios like aggregating data from multiple sources, combining logs from different servers, or processing events from various producers. Your task is to implement a Fan-In pattern in Go using channels to manage the input and output streams.
Problem Description
You need to create a Go program that implements the Fan-In pattern. The program should accept multiple input channels, each producing integer values. It should then merge these input channels into a single output channel, which emits the combined stream of integers. The output channel should emit the integers in the order they are received from the input channels (FIFO order). The program should gracefully handle the termination of input channels (when an input channel is closed). The output channel should be closed when all input channels are closed.
Key Requirements:
- Multiple Input Channels: The program should accept a variable number of input channels.
- Single Output Channel: The program should produce a single output channel.
- FIFO Ordering: The output channel should maintain the order of elements as received from the input channels.
- Graceful Termination: The program should handle the closure of input channels correctly. The output channel should only be closed after all input channels are closed.
- Error Handling: While the problem focuses on data merging, consider how you might handle errors if the input channels were producing errors (though error handling is not explicitly required for this challenge).
Expected Behavior:
The program should continuously read values from the input channels, merge them into the output channel, and close the output channel when all input channels are closed.
Edge Cases to Consider:
- Empty input channels: What happens if an input channel is immediately closed?
- Variable number of input channels: The program should work correctly regardless of how many input channels are provided.
- Input channels closing at different times: The program should handle this gracefully and ensure the output channel is closed only when all inputs are closed.
Examples
Example 1:
Input: Three input channels:
Channel 1: [1, 2, 3]
Channel 2: [4, 5]
Channel 3: [6]
Output: [1, 4, 6, 2, 5, 3]
Explanation: The integers are emitted in the order they are received from the input channels.
Example 2:
Input: Two input channels:
Channel 1: [1, 2]
Channel 2: [] (Channel 2 is immediately closed)
Output: [1, 2]
Explanation: The program reads from Channel 1 until it's closed, then closes the output channel.
Example 3: (Edge Case)
Input: Four input channels, all immediately closed:
Channel 1: []
Channel 2: []
Channel 3: []
Channel 4: []
Output: [] (Output channel is immediately closed)
Explanation: Since there are no values to emit, the output channel is closed immediately.
Constraints
- The input channels will only produce integer values.
- The number of input channels can range from 0 to 100.
- The program should be efficient in terms of memory usage. Avoid buffering large amounts of data.
- The program should be well-structured and readable.
Notes
- Consider using a
sync.WaitGroupto track the number of active input channels. This will help you determine when all input channels have been closed. - Channels are a powerful tool for concurrent programming in Go. Think about how you can use channels to coordinate the reading from input channels and the writing to the output channel.
- The Fan-In pattern is a fundamental building block for many distributed systems. Understanding this pattern is crucial for building scalable and reliable applications.