liveBook · Manning

Fan-in

As explained in Learn Concurrent Programming with Go

A fan-in pattern merges values from multiple concurrent sources into a single stream.

Fan-in merges values from multiple channels into one stream, allowing independent concurrent stages to feed a single downstream stage. section 9.2.3

A reliable fan-in implementation:

  • Creates one forwarding goroutine for each input channel. section 9.2.3
  • Sends every received value to a shared output channel. section 9.2.3
  • Uses a sync.WaitGroup so the shared channel closes only after every input channel is drained. section 9.2.3
  • Uses a quit channel to let forwarding goroutines stop before consuming all input. section 9.2.3

Accounting streams

A select loop reads interleaved sales and expenses, subtracts expenses from sales, and sets each channel to nil after closure. The loop ends when both channels are nil. This fixed-source form works for two known inputs; dynamic source counts require a separate fan-in function. section 8.1.6

Listing 9.10 Implementing a fan-in function
package listing9_10

import (
    "sync"
)

func FanIn[K any](quit <-chan int, allChannels ...<-chan K) chan K {
    wg := sync.WaitGroup{}              #1
    wg.Add(len(allChannels))            #1
    output := make(chan K)              #2
    for _, c := range allChannels {
        go func(channel <-chan K) {     #3
            defer wg.Done()             #4
            for i := range channel {
                select {
                case output <- i:       #5
                case <-quit:            #6
                    return              #6
                }
            }
        }(c)                            #7
    }
    go func() {                         #8
        wg.Wait()                       #8
        close(output)                   #8
    }()
    return output                       #9
}
#1 Creates a waitgroup, setting the size to be equal to the number of input channels
#2 Creates the output channel
#3 Starts a goroutine for every input channel
#4 Once the goroutine terminates, marks the waitgroup as done
#5 Forwards each received message to the shared output channel
#6 If quit channel is closed, terminates the goroutine
#7 Passes one input channel to the goroutine
#8 Waits for all the goroutines to finish and then closes the output channel
#9 Returns the output channel

Inspect the complete FanIn function, including per-channel forwarding goroutines, cancellation, WaitGroup coordination, and output closure. section 9.2.3

How Learn Concurrent Programming with Go covers it

How deep it goes
Explains fixed-source select fan-in and dynamic-source forwarding, including cancellation and coordinated channel closure.
Examples
Uses an accounting stream and a web-page pipeline with twenty downloaders feeding extractWords through FanIn.
What you can do after
Build it from scratch with forwarding goroutines, a shared output channel, cancellation, and WaitGroup-based closure.
How it connects
Connects channels, goroutines, pipelines, fan-out, quit channels, WaitGroup, and message passing.

Also explained in

Compare how 2 books explain fan-in →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Concurrent Programming with Go. The section links point to the parts of the book it draws on.