Skip to content

Instantly share code, notes, and snippets.

@daehee
Created December 22, 2020 03:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save daehee/859c6a3d9f14b0263665a5ab58f0692e to your computer and use it in GitHub Desktop.
Save daehee/859c6a3d9f14b0263665a5ab58f0692e to your computer and use it in GitHub Desktop.
or-done & tee
func orDone(done, c <-chan interface{}) <-chan interface{} {
valStream := make(chan interface{})
go func() {
defer close(valStream)
for {
select {
case <-done:
return
case v, ok := <-c:
if ok == false {
return
}
select {
case valStream <- v:
case <-done:
}
}
}
}()
return valStream
}
func tee(done <-chan interface{}, in <-chan interface{}) (<-chan interface{}, <-chan interface{}) {
out1 := make(chan interface{})
out2 := make(chan interface{})
go func() {
defer close(out1)
defer close(out2)
for val := range orDone(done, in) {
var out1, out2 = out1, out2 // Shadow variables for closure
// Two iterations of select statement for each outbound channel
for i := 0; i < 2; i++ {
// Select so that out1 and out2 don't block each other
select {
case <-done:
case out1 <- val:
// Set shadowed variable to nil so that further writes will block
// and other channel can continue
out1 = nil
case out2 <- val:
out2 = nil
}
}
}
}()
return out1, out2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment