В одном проекте мне необходимо было получать из одного источника данные и, в зависимости от текущего состояния, отдавать эти данные одному из множества ресиверов. Схему можно описать так: если некуда отдавать данные, то они должны просто обнуляться (либо - для любителей статистики - инкрементировать соответствующий счетчик); в случае готовности одного из ресиверов принимать данные - отдавать их ему. По условиям задачи ресивер готовый принимать данные всегда один.

В языке go есть такая конструкция:

for {
        select {
        case <-ch1:
                doThing1()
        case <-ch2:
                doThing2()
        }
}

позволяющая читать с рандомного канала в котором есть данные.

Если ее немного изменить, то вполне подходит для решения:

package main

import (
        "context"
        "fmt"
        "time"
)

var (
        ii, ia, ib, ic int64

        ctx    context.Context
        cancel context.CancelFunc

        a_a = make(chan bool)
        b_b = make(chan bool)
        c_c = make(chan bool)
)

func gen() {
        for i := 0; i < 1000000000; i++ {
                select {
                case a_a <- true:
                        ia++
                case b_b <- true:
                        ib++
                case c_c <- true:
                        ic++
                }
                ii++
        }
}

func recv(ctx context.Context, ch chan bool, i int64) {
        for {
                select {
                case <-ctx.Done():
                        fmt.Println(i)
                        return
                case <-ch:
                        i++
                }
        }
}

func swap(i int64) {
        switch i {
        case 1:
                if ctx != nil {
                        cancel()
                }
                ctx, cancel = context.WithCancel(context.Background())
                go recv(ctx, a_a, ia)
        case 2:
                if ctx != nil {
                        cancel()
                }
                ctx, cancel = context.WithCancel(context.Background())
                go recv(ctx, b_b, ib)
        case 3:
                if ctx != nil {
                        cancel()
                }
                ctx, cancel = context.WithCancel(context.Background())
                go recv(ctx, c_c, ic)
        case 4:
                if ctx != nil {
                        cancel()
                }
        }
}

func main() {
        swap(1)
        time.Sleep(time.Second)
        swap(2)
        time.Sleep(time.Second)
        swap(3)
        time.Sleep(time.Second)
        swap(4)

        time.Sleep(time.Second)

        fmt.Println(ii - (ia+ib+ic))
}

func init() {
        go gen()
}

/* вывод
2704715
2730004
2741948
0
*/