Infrastructure Go daemon
SECTION 7.1

Fan-Out / Fan-In

Fan-out: distribute work across multiple goroutines. Fan-in: collect results into one channel.

2 · Worked example — read every step
// Fan-out: launch N workers reading from the same input channel
func fanOut(input <-chan string, workers int) []<-chan Result {
    channels := make([]<-chan Result, workers)
    for i := 0; i < workers; i++ {
        channels[i] = worker(input)
    }
    return channels
}

func worker(input <-chan string) <-chan Result {
    out := make(chan Result)
    go func() {
        defer close(out)
        for item := range input {
            out <- process(item)
        }
    }()
    return out
}

// Fan-in: merge multiple result channels into one
func fanIn(channels ...<-chan Result) <-chan Result {
    var wg sync.WaitGroup
    merged := make(chan Result)

    for _, ch := range channels {
        wg.Add(1)
        go func(c <-chan Result) {
            defer wg.Done()
            for val := range c {
                merged <- val
            }
        }(ch)
    }

    go func() {
        wg.Wait()
        close(merged)
    }()
    return merged
}

Real uses: Checking N servers in parallel, validating N config files, downloading N artifacts.

3 · Fill the gaps
Fan-in, from memory — the merged channel must end exactly when the last forwarder finishes.
func fanIn(channels ...<-chan Result) <-chan Result {
    var wg sync.WaitGroup
    merged := make(chan Result)

for _, ch := range channels {
    wg.Add(1)
    go func(c &lt;-chan Result) {
        defer <span class="gap-slot"><input class="gap-input" data-answer="wg.Done()" size="11" spellcheck="false" autocomplete="off" autocapitalize="off"></span>
        for val := range c {
            <span class="gap-slot"><input class="gap-input" data-answer="merged &lt;- val" size="15" spellcheck="false" autocomplete="off" autocapitalize="off"></span>
        }
    }(ch)
}

go func() {
    <span class="gap-slot"><input class="gap-input" data-answer="wg.Wait()" size="11" spellcheck="false" autocomplete="off" autocapitalize="off"></span>
    <span class="gap-slot"><input class="gap-input" data-answer="close(merged)" size="15" spellcheck="false" autocomplete="off" autocapitalize="off"></span>
}()
return merged

}