func (b *Breaker) Go(work func() error) error {
	state := atomic.LoadUint32(&b.state)
	if state == open {
		return ErrBreakerOpen
	}
	go b.doWork(state, work)
	return nil
}
Go will either return ErrBreakerOpen immediately if the circuit-breaker is
already open, or it will run the given function in a separate goroutine.
If the function is run, Go will return nil immediately, and will *not* return
the return value of the function. It is safe to call Go concurrently on the
same Breaker.
package breaker
import (
	"errors"
	"sync"
	"sync/atomic"
	"time"
)
var ErrBreakerOpen = errors.New("circuit breaker is open")
const (
	closed uint32 = iota
	open
	halfOpen
)
type Breaker struct {
	errorThreshold, successThreshold int
	timeout                          time.Duration
	lock              sync.Mutex
	state             uint32
	errors, successes int
	lastError         time.Time
}
func New(errorThreshold, successThreshold int, timeout time.Duration) *Breaker {
	return &Breaker{
		errorThreshold:   errorThreshold,
		successThreshold: successThreshold,
		timeout:          timeout,
	}
}
func (b *Breaker) Run(work func() error) error {
	state := atomic.LoadUint32(&b.state)
	if state == open {
		return ErrBreakerOpen
	}
	return b.doWork(state, work)
}