Go: One producer many consumers

后端 未结 4 1719
情话喂你
情话喂你 2021-02-02 13:56

So I have seen a lot of ways of implementing one consumer and many producers in Go - the classic fanIn function from the Concurrency in Go talk.

What I want is a fanOut

4条回答
  •  孤城傲影
    2021-02-02 14:06

    You pretty much described the best way to do it but here is a small sample of code that does it.

    Go playground: https://play.golang.org/p/jwdtDXVHJk

    package main
    
    import (
        "fmt"
        "time"
    )
    
    func producer(iters int) <-chan int {
        c := make(chan int)
        go func() {
            for i := 0; i < iters; i++ {
                c <- i
                time.Sleep(1 * time.Second)
            }
            close(c)
        }()
        return c
    }
    
    func consumer(cin <-chan int) {
        for i := range cin {
            fmt.Println(i)
        }
    }
    
    func fanOut(ch <-chan int, size, lag int) []chan int {
        cs := make([]chan int, size)
        for i, _ := range cs {
            // The size of the channels buffer controls how far behind the recievers
            // of the fanOut channels can lag the other channels.
            cs[i] = make(chan int, lag)
        }
        go func() {
            for i := range ch {
                for _, c := range cs {
                    c <- i
                }
            }
            for _, c := range cs {
                // close all our fanOut channels when the input channel is exhausted.
                close(c)
            }
        }()
        return cs
    }
    
    func fanOutUnbuffered(ch <-chan int, size int) []chan int {
        cs := make([]chan int, size)
        for i, _ := range cs {
            // The size of the channels buffer controls how far behind the recievers
            // of the fanOut channels can lag the other channels.
            cs[i] = make(chan int)
        }
        go func() {
            for i := range ch {
                for _, c := range cs {
                    c <- i
                }
            }
            for _, c := range cs {
                // close all our fanOut channels when the input channel is exhausted.
                close(c)
            }
        }()
        return cs
    }
    
    func main() {
        c := producer(10)
        chans := fanOutUnbuffered(c, 3)
        go consumer(chans[0])
        go consumer(chans[1])
        consumer(chans[2])
    }
    

    The important part to note is how we close the output channels once the input channel has been exhausted. Also if one of the output channels blocks on the send it will hold up the send on the other output channels. We control the amount of lag by setting the buffer size of the channels.

提交回复
热议问题