code: func (b *CircularBuffer) NBPush(v interface{}) interface{} {
  	var evictv interface{}
  	b.lock.Lock()
  
  	if b.buffer[b.pos] != nil {
  		panic("not nil")
  	}
  
  	b.buffer[b.pos] = v
  	b.pos = (b.pos + 1) % b.size
  	if b.pos == b.start {
  		// Remove old item from the bottom of the stack to
  		// free the space for the new one. This doesn't change
  		// the length of the stack, so no need to touch avail.
  		evictv = b.buffer[b.start]
  		b.buffer[b.start] = nil
  		b.start = (b.start + 1) % b.size
  	} else {
  		select {
  		case b.avail <- true:
  		default:
  			panic("Sending to avail channel must never block")
  		}
  	}
  	b.lock.Unlock()
  	if evictv != nil && b.Evict != nil {
  		// Outside the lock. User callback may in want to add
  		// an item to the stack.
  		b.Evict(evictv)
  		return nil
  	}
  	return evictv
  }
docs: // Nonblocking push. If the Evict callback is not set returns the
  // evicted item (if any), otherwise nil.