for i := range jobs {
job()
}
👨💻Middle Go разработчик:
var wg sync.WaitGroup
for i := range jobs {
wg.Add(1)
go func(job jobType) {
defer wg.Done()
job()
}(jobs[i])
}
wg.Wait()
👨💻Senior Go разработчик:
var workersNum = runtime.NumCPU()
var (
wg sync.WaitGroup
in = make(chan jobType, workersNum)
)
for i := 0; i < workersNum; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for job := range in {
job()
}
}()
}
for i := range jobs {
in <- jobs[i]
}
close(in)
wg.Wait()
🧠Lead Go разработчик:
import "github.com/sourcegraph/conc/iter"
iterator := iter.Iterator[jobType]{MaxGoroutines: runtime.NumCPU()}
iterator.ForEach(jobs, func(job jobType) {
job()
})
Да, асинхронность в 👩💻 довольно изящна и проста (если сравнивать с другими языками). Но все же она требует от разработчика внимательности и хорошего знания языка. А в случае ошибки вам будет обеспечена утечка памяти или deadlock.
Что отличает ведущего (Lead) разработчика от других? Он пишет эффективные решения довольно быстро, а главное эти решения надежные и, в идеале, изящны. Часто это достигается путем использования проверенных инструментов.
Одним из таких инструментов - github.com/sourcegraph/concНа мой взгляд это то, чего не хватает в стандартной библиотеке Go. Максимально изящная асинхронность, спрятанная за синтаксическим сахаром. С этой библиотекой шансов словить утечку памяти резко уменьшаются, а скорость проведения код ревью увеличивается.
Делайте вещи проще! (KISS)