DevPrep
  • Interview Prep
  • Projects
  • Resources
  • Pricing
  • About Us
Submit Question
DevPrep
  • Pricing
  • About Us
Submit Question

Practice

  • JavaScript
  • DSA
  • Machine Coding
  • System Design

Resources

  • Learning Tracks
  • Articles
  • Roadmaps
  • Compare Concepts
  • Glossary
  • Developer Tools
  • All Questions

Company

  • About
  • Pricing

Legal

  • Privacy Policy
  • Terms of Service
DevPrep

© 2026 DevPrep. All rights reserved.

← Back to Questions
MediumMachine Coding

Implement Fan-In Pattern: Merge Multiple Channels

214 views

Problem Statement

Implement a fan-in function that merges N input channels into a single output channel. Close the output channel only when all inputs are closed.

Implementation

package fanin

import "sync"

func Merge[T any](channels ...<-chan T) <-chan T {
    out := make(chan T)
    var wg sync.WaitGroup
    
    // Start a goroutine for each input channel
    for _, ch := range channels {
        wg.Add(1)
        go func(c <-chan T) {
            defer wg.Done()
            for val := range c {
                out <- val
            }
        }(ch)
    }
    
    // Close output when all inputs are done
    go func() {
        wg.Wait()
        close(out)
    }()
    
    return out
}

Usage Example

func main() {
    // Create input channels
    ch1 := make(chan int)
    ch2 := make(chan int)
    ch3 := make(chan int)
    
    // Start producers
    go func() {
        for i := 0; i < 5; i++ {
            ch1 <- i * 10
        }
        close(ch1)
    }()
    
    go func() {
        for i := 0; i < 5; i++ {
            ch2 <- i * 100
        }
        close(ch2)
    }()
    
    go func() {
        for i := 0; i < 5; i++ {
            ch3 <- i * 1000
        }
        close(ch3)
    }()
    
    // Merge and consume
    merged := fanin.Merge(ch1, ch2, ch3)
    for val := range merged {
        fmt.Println(val)
    }
}

Fan-In with Context Cancellation

func MergeWithCancel[T any](ctx context.Context, channels ...<-chan T) <-chan T {
    out := make(chan T)
    var wg sync.WaitGroup
    
    for _, ch := range channels {
        wg.Add(1)
        go func(c <-chan T) {
            defer wg.Done()
            for {
                select {
                case val, ok := <-c:
                    if !ok {
                        return
                    }
                    select {
                    case out <- val:
                    case <-ctx.Done():
                        return
                    }
                case <-ctx.Done():
                    return
                }
            }
        }(ch)
    }
    
    go func() {
        wg.Wait()
        close(out)
    }()
    
    return out
}

Related Pattern: Fan-Out

func FanOut[T any](input <-chan T, n int) []<-chan T {
    outputs := make([]chan T, n)
    for i := range outputs {
        outputs[i] = make(chan T)
    }
    
    go func() {
        defer func() {
            for _, ch := range outputs {
                close(ch)
            }
        }()
        
        i := 0
        for val := range input {
            outputs[i] <- val
            i = (i + 1) % n
        }
    }()
    
    result := make([]<-chan T, n)
    for i, ch := range outputs {
        result[i] = ch
    }
    return result
}

Sample Test Cases

Case 1
Input
channels=[ch1{1,2}, ch2{3,4}]
Expected Output
Merged output contains 1,2,3,4 (order may vary)
Case 2
Input
channels=[ch1{}, ch2{1}]
Expected Output
Handles empty channels gracefully
Case 3
Input
[]
Expected Output
[]
Case 4
Input
[{"type": "int", "values": [1, 2, 3]}, {"type": "int", "values": [4, 5]}]
Expected Output
[1, 2, 3, 4, 5]
Case 5
Input
[{"type": "string", "values": ["a", "b"]}, {"type": "string", "values": []}, {"type": "string", "values": ["c"]}]
Expected Output
["a", "b", "c"]

No solutions yet

Be the first to share a solution for this question.

Comments (0)

Sign in to leave a comment.

No comments yet. Be the first to comment.

Stats

Views
214
Likes
0
Solutions
0
Comments
0

Category

Backend Engineering

Languages

Go