Go Tee-Channel: Difference between revisions
Jump to navigation
Jump to search
(→tee()) |
|||
(One intermediate revision by the same user not shown) | |||
Line 3: | Line 3: | ||
=Overview= | =Overview= | ||
This pattern allows duplicating and splitting the values coming in from a channel into two different output channels. | This pattern allows duplicating and splitting the values coming in from a channel into two different output channels. | ||
=<tt>tee()</tt>= | |||
This example uses <code>orDone()</code> described in the [[Go_OR-Done-Channel_Pattern#orDone()|OR-Done-Channel Pattern]] section. | |||
<syntaxhighlight lang='go'> | |||
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 | |||
} | |||
</syntaxhighlight> |
Latest revision as of 23:15, 5 February 2024
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
}