code: func batchOp(total int, op func(start, end int) error) error {
  	switch {
  	case total == 0:
  		return nil
  	case total <= batchSize:
  		return op(0, total)
  	}
  
  	errs := make(chan error)
  	ops := 0
  	offset := 0
  	for total > 0 {
  		count := batchSize
  		if count > total {
  			count = total
  		}
  		go func(start, end int) {
  			errs <- op(start, end)
  		}(offset, offset+count)
  		offset += count
  		total -= count
  		ops++
  	}
  
  	var all errors.MultiError
  	for i := 0; i < ops; i++ {
  		err := <-errs
  		if merr, yep := err.(errors.MultiError); yep {
  			for _, e := range merr {
  				if e != nil {
  					all = append(all, e)
  				}
  			}
  		} else if err != nil {
  			all = append(all, err)
  		}
  	}
  
  	if len(all) == 0 {
  		return nil
  	}
  	return all
  }
docs: // batchOp splits 'total' into batches and calls 'op' in parallel.
  //
  // Doesn't preserve order of returned errors! Don't try to deconstruct the
  // returned multi error, the position of individual errors there does not
  // correlate with the original array.