Да многопоточность сильно поможет Вам особенно если массив очень большой
Попробуйте вот так
1 2 3 4 5 6 7 8 9 10 11 |
func doubleSlice(s []int) { var wg sync.WaitGroup for i := range s { wg.Add(1) go func(i int) { defer wg.Done() s[i] = s[i] * 2 }(i) } wg.Wait() } |
elena: А чем RabbitMq не нравится или redis queue ?
@elena а зачем настраивать и использовать какое то дополнительное обеспечение если нужно для решения одной просто задачи! Они хорошо подходят для решения сложных задач - к примеру Вы посылаете миллионы писем в день! А иногда нужно что то простое!
monte: Да многопоточность сильно поможет Вам особенно если массив очень большой Попробуйте вот такfunc doubleSlice(s []int) { var wg sync.WaitGroup for i := range s { wg.Add(1) go func(i int) { defer wg.Done() s[i] = s[i] * 2 }(i) } wg.Wait()
тут будет `data race`, ибо пишем в параллельных процессах (горутинах) в одну и туже область памяти (срез `i`)
проверить можно так `go run -race ./main.go`
я решал проблему гонки данных через канал, а в частности описанная выше калькуляция решается примерно следующим образом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
package main import ( "fmt" "sync" ) func main() { var sliceElementCount int64 = 2048 // аллокация среза s := make([]int64, 0, sliceElementCount) // генерирует срез for i := int64(1); i <= sliceElementCount; i++ { s = append(s, i) } resultDoubleSlice := doubleSlice(s) fmt.Println(resultDoubleSlice) } // тип для результат калькуляции type queueCalcResult struct { id int val int64 } // функция, обсчета среза func doubleSlice(s []int64) []int64 { // определяет длину среза, которую надо обработать stackLength := len(s) // создаем срез для результатов калькуляции result := make([]int64, stackLength) // создание waitGroup для синхронизации wg := new(sync.WaitGroup) // устанавливаем мощность группы ожидания wg.Add(stackLength) // создаём буферезированный канал, размерностью равной длине входного среза (можно задать иное значение, но какое?) queueTaskChannel := make(chan queueCalcResult, stackLength) // пробегаемся по срезу for i, j := range s { // ... порождаю калькуляцию в горутине go calc(wg, queueTaskChannel, i, j) } // ждем, когда отработаю все горутины wg.Wait() // закрываем канал с результами калькуляции close(queueTaskChannel) // читаем из канала for item := range queueTaskChannel { result[item.id] = item.val } return result } // функция калькуляции func calc(wg *sync.WaitGroup, queue chan<- queueCalcResult, key int, val int64) { defer wg.Done() // пушим результат калькуляции в канал queue <- queueCalcResult{key, val * 2} } |
@monte