Если вам нужны все результаты, вам не нужен канал (и дополнительная процедура для его закрытия), чтобы сообщить о результатах, вы можете написать непосредственно в срез результатов:
func cleaner(data []string) []string {
results := make([]string, len(data))
wg := &sync.WaitGroup{}
wg.Add(len(data))
for i, item := range data {
go func(i int, item string) {
defer wg.Done()
results[i] = doWork(item)
}(i, item)
}
wg.Wait()
return results
}
Этовозможно, потому что элементы слайса действуют как отдельные переменные, и поэтому могут быть записаны индивидуально без синхронизации.Подробнее см. Могу ли я одновременно написать разные элементы среза .Вы также получите результаты в том же порядке, что и ваши входные данные бесплатно.
Вариант анотера: если doWork()
не вернет результат, но получит адрес, где результат должен быть "помещен", и дополнительно sync.WaitGroup
, чтобы сообщить о завершении, эту функцию doWork()
можно выполнить «напрямую» как новую процедуру.
Мы можем создать многоразовую оболочку для doWork()
:
func doWork2(item string, result *string, wg *sync.WaitGroup) {
defer wg.Done()
*result = doWork(item)
}
Если выиметь логику обработки в таком формате, вот как она может выполняться одновременно:
func cleanest(data []string) []string {
results := make([]string, len(data))
wg := &sync.WaitGroup{}
wg.Add(len(data))
for i, item := range data {
go doWork2(item, &results[i], wg)
}
wg.Wait()
return results
}
Еще одним вариантом может быть передача канала в doWork()
, по которому предполагается доставить результат.Это решение даже не требует sync.Waitgroup
, поскольку мы знаем, сколько элементов мы хотим получить от канала:
func cleanest2(data []string) []string {
ch := make(chan string)
for _, item := range data {
go doWork3(item, ch)
}
results := make([]string, len(data))
for i := range results {
results[i] = <-ch
}
return results
}
func doWork3(item string, res chan<- string) {
res <- "done:" + item
}
«Слабость» этого последнего решения заключается в том, что оно может собирать результат »не в порядке »(что может быть или не быть проблемой).Этот подход можно улучшить, чтобы сохранить порядок, позволяя doWork()
получать и возвращать индекс элемента.Подробности и примеры см. В Как собрать значения из N процедур, выполненных в определенном порядке?