import "container/ring" // Use a goroutine to receive values from `out` and store them // in an auto-expanding buffer, so that sending to `out` never blocks. // Return a channel which serves as a sending proxy to to `out`. func sendproxy(out chan<- int) chan<- int { in := make(chan int, 100) go func() { n := 1000 // the allocated length of the circular queue first := ring.New(n) last := first var c chan<- int var e int var ok bool for { select { case e = <-in: for added := 0; added < 1000; added++ { if closed(in) { in = nil break } last.Value = e if last.Next() == first { // buffer full: expand it last.Link(ring.New(n)) n *= 2 } last = last.Next() if e, ok = <-in; !ok { break } } c = out // enable output e = first.Value.(int) case c <- e: for { first = first.Next() if first == last { // buffer empty: disable output if in == nil { close(out) return } c = nil break } e = first.Value.(int) if ok = c <- e; !ok { break } } } } }() return in }