func (rl *RateLimiter) LimitedGo(f process.ProcessFunc) {

	<-rl.limiter
	p := rl.Go(f)

	// this <-closed() is here because the child may have spawned
	// children of its own, and our rate limiter should capture that.
	go func() {
		<-p.Closed()
		rl.limiter <- struct{}{}
	}()
}
func (rl *RateLimiter) LimitedGo(f process.ProcessFunc) {

	<-rl.limiter
	p := rl.Go(f)

	// this <-closed() is here because the child may have spawned
	// children of its own, and our rate limiter should capture that.
	go func() {
		<-p.Closed()
		rl.limiter <- struct{}{}
	}()
}
// LimitedGo creates a new process, adds it as a child, and spawns the
// ProcessFunc f in its own goroutine, but may block according to the
// internal rate limit. It is equivalent to:
//
//   func(f process.ProcessFunc) {
//      <-limitch
//      p.Go(func (child process.Process) {
//        f(child)
//        f.Close() // make sure its children close too!
//        limitch<- struct{}{}
//      })
///  }
//
// It is useful to construct simple asynchronous workers, children of p,
// and rate limit their creation, to avoid spinning up too many, too fast.
// This is great for providing backpressure to producers.