package main import "fmt" type T interface{} type Buf struct { depositc, fetchc chan T; } func when(b bool, c chan T) chan T { if b {return c} else {return nil} } func (buf *Buf) init() { buf.depositc = make(chan T) buf.fetchc = make(chan T) go func () { n := 10 buffer:= make([]T, n) front, rear, count := 0, 0, 0 for { select { case when(count > 0, buf.fetchc) <- buffer[rear]: rear = (rear + 1) % n; count-- case buffer[front] = <-when(count < n, buf.depositc): front = (front + 1) % n; count++ } } }() } func (buf *Buf) fetch() T { return <-buf.fetchc } func (buf *Buf) deposit(a T) { buf.depositc <- a} func main() { var buf Buf buf.init() go func () { for i := 0; i<20; i++ { fmt.Printf("Sending %d\n", i) buf.deposit(i) } }() for i := 0; i<20; i++ { x := buf.fetch() fmt.Printf(" Got %d\n", x) } }