package main import ( "fmt" "math/rand" "sync" "time" ) func main() { p := NewPool(5) wg := sync.WaitGroup{} for i := 0; i < 10; i++ { wg.Add(1) go func() { n := p.Get() fmt.Println("start working on: ", n) time.Sleep(time.Duration(n) * time.Second) fmt.Println("done working on: ", n) p.Put(n) wg.Done() }() } wg.Wait() } type pool struct { c chan int free chan int } func NewPool(size int) *pool { p := &pool{ c: make(chan int, size), free: make(chan int, size), } // put 5 tokens onto the free channel for i := 0; i < size; i++ { p.free <- 1 } return p } func (p *pool) Get() (n int) { select { case n = <-p.c: case <-p.free: // take a token // block if we've used up all available tokens // tokens don't get put back. fmt.Println("(get) default free") n = rand.Intn(9) + 1 } return } func (p *pool) Put(n int) { select { case p.c <- n: default: fmt.Println("This should never be called", n) } }