func (b *Bucket) Take(n int64) (taken int64) {
	for {
		if tokens := atomic.LoadInt64(&b.tokens); tokens == 0 {
			return 0
		} else if n <= tokens {
			if !atomic.CompareAndSwapInt64(&b.tokens, tokens, tokens-n) {
				continue
			}
			return n
		} else if atomic.CompareAndSwapInt64(&b.tokens, tokens, 0) {  
			return tokens
		}
	}
}
Take attempts to take n tokens out of the bucket.
If tokens == 0, nothing will be taken.
If n <= tokens, n tokens will be taken.
If n > tokens, all tokens will be taken.

This method is thread-safe.
package tb
import (
	"math"
	"sync/atomic"
	"time"
)
type Bucket struct {
	inc      int64
	tokens   int64
	capacity int64
	freq     time.Duration
	closing  chan struct{}
}
func NewBucket(c int64, freq time.Duration) *Bucket {
	b := &Bucket{tokens: c, capacity: c, closing: make(chan struct{})}
	if freq == -1 {
		return b
	} else if evenFreq := time.Duration(1e9 / c); freq < evenFreq {
		freq = evenFreq
	}
	b.freq = freq
	b.inc = int64(math.Floor(.5 + (float64(c) * freq.Seconds())))
	go b.fill()
	return b
}