func (p StringBatchProcessor) Run() ([]string, error) {
	p.prime()
	var wg sync.WaitGroup
	defer p.mu.Unlock()
	p.mu.Lock()
	if len(p.primedJobs) == 0 {
		return []string{}, nil
	}

	allDone := make(chan struct{})
	results := make([]string, len(p.primedJobs))
	for index, toExecute := range p.primedJobs {
		wg.Add(1)
		go func(index int, functionToExecute func(<-chan struct{}) (string, error)) {
			defer wg.Done()
			result, err := functionToExecute(p.t.Dying())
			if err != nil {
				p.t.Kill(errors.New(string(index) + ": " + err.Error()))
			}
			results[index] = result
		}(index, toExecute)
	}

	// Start a goroutine to wait for every process to finish.
	go func() {
		wg.Wait()
		close(allDone)
	}()

	// Wait for them all to finish, or one to
	select {
	case <-allDone:
	case <-p.t.Dying():
	}
	p.t.Done()
	return results, p.t.Err()
}
// Start runs all the given functions concurrently until either they all complete or one returns an error, in which case it returns that error.
// The functions are passed a channel which will be closed when the function should stop.
Start runs all the given functions concurrently until either they all complete or one returns an error, in which case it returns that error.
The functions are passed a channel which will be closed when the function should stop.
// Start runs all the given functions concurrently until either they all complete or one returns an error in which case it returns that error . // The functions are passed a channel which will be closed when the function should stop .
func (p StringBatchProcessor) Run() ([]string, error) {
	p.prime()
	var wg sync.WaitGroup
	defer p.mu.Unlock()
	p.mu.Lock()
	if len(p.primedJobs) == 0 {
		return []string{}, nil
	}
	allDone := make(chan struct{})
	results := make([]string, len(p.primedJobs))
	for index, toExecute := range p.primedJobs {
		wg.Add(1)
		go func(index int, functionToExecute func(<-chan struct{}) (string, error)) {
			defer wg.Done()
			result, err := functionToExecute(p.t.Dying())
			if err != nil {
				p.t.Kill(errors.New(string(index) + ": " + err.Error()))
			}
			results[index] = result
		}(index, toExecute)
	}
	go func() {
		wg.Wait()
		close(allDone)
	}()
	select {
	case <-allDone:
	case <-p.t.Dying():
	}
	p.t.Done()
	return results, p.t.Err()
}
func ( p StringBatchProcessor ) Run ( ) ( [ ] string , error ) { p . prime ( ) var wg sync . WaitGroup defer p . mu . Unlock ( ) p . mu . Lock ( ) if len ( p . primedJobs ) == 0 { return [ ] string { } , nil } allDone := make ( chan struct { } ) results := make ( [ ] string , len ( p . primedJobs ) ) for index , toExecute := range p . primedJobs { wg . Add ( 1 ) go func ( index int , functionToExecute func ( <- chan struct { } ) ( string , error ) ) { defer wg . Done ( ) result , err := functionToExecute ( p . t . Dying ( ) ) if err != nil { p . t . Kill ( errors . New ( string ( index ) + " " + err . Error ( ) ) ) } results [ index ] = result } ( index , toExecute ) } go func ( ) { wg . Wait ( ) close ( allDone ) } ( ) select { case <- allDone : case <- p . t . Dying ( ) : } p . t . Done ( ) return results , p . t . Err ( ) }
Start runs all the given functions concurrently until either they all complete or one returns an error, in which case it returns that error.
Start runs all the given functions concurrently until either they all complete or one returns an error in which case it returns that error .
// Start a goroutine to wait for every process to finish. // Wait for them all to finish, or one to