Я работаю над подбором нескольких шаблонов параллелизма Go. Я посмотрел на реализацию фоновых рабочих с использованием горутин и каналов ввода/вывода и заметил, что когда я отправляю новые задания на принимающий канал (по сути, ставлю новые задания в очередь), я должен делать это в горутине, иначе планирование испортится. Значение:
Это вылетает:
for _, jobData := range(dataSet) {
input <- jobData
}
Это работает:
go func() {
for _, jobData := range(dataSet) {
input <- jobData
}
}()
Для чего-то более конкретного я поэкспериментировал с каким-то бессмысленным кодом (вот он на игровой площадке):
package main
import (
"log"
"runtime"
)
func doWork(data int) (result int) {
// ... some 'heavy' computation
result = data * data
return
}
// do the processing of the input and return
// results on the output channel
func Worker(input, output chan int) {
for data := range input {
output <- doWork(data)
}
}
func ScheduleWorkers() {
input, output := make(chan int), make(chan int)
for i := 0 ; i < runtime.NumCPU() ; i++ {
go Worker(input, output)
}
numJobs := 20
// THIS DOESN'T WORK
// and crashes the program
/*
for i := 0 ; i < numJobs ; i++ {
input <- i
}
*/
// THIS DOES
go func() {
for i := 0 ; i < numJobs ; i++ {
input <- i
}
}()
results := []int{}
for i := 0 ; i < numJobs ; i++ {
// read off results
result := <-output
results = append(results, result)
// do stuff...
}
log.Printf("Result: %#v\n", results)
}
func main() {
ScheduleWorkers()
}
Я пытаюсь понять эту тонкую разницу - помощь приветствуется. Спасибо.