Go Tee-Channel

From NovaOrdis Knowledge Base
Jump to navigation Jump to search

Internal

Overview

This pattern allows duplicating and splitting the values coming in from a channel into two different output channels.

tee()

This example uses orDone() described in the OR-Done-Channel Pattern section.

func tee(done <-chan interface{}, in <-chan interface{}) (_, _ <-chan interface{}) {
	out1 := make(chan interface{})
	out2 := make(chan interface{})
	go func() {
		defer close(out1)
		defer close(out2)
		for v := range orDone(done, in) {
			var out1, out2 = out1, out2 // We use the local versions of out1 and out2, so we shadow these variables.
			for i := 0; i < 2; i++ {
				// We are going to use one select statement so that writes to out1 and out2 don't block each other.
				// To ensure both are written to, we do it in a 2-step loop.
				select {
				case <-done:
				case out1 <- v:
					// once we've written on a channel, we set the shadowed copy to nil
					// so that further writes will block and the other channel may continue
					out1 = nil
				case out2 <- v:
					// once we've written on a channel, we set the shadowed copy to nil
					// so that further writes will block and the other channel may continue
					out2 = nil
				}
			}
		}
	}()
	return out1, out2
}