res равен nil, map изменяется конкурентно, а канал закрывается до завершения отправителей. Проще передать значения в main и дать ему единолично заполнить map.
Обнаружение и исправление багов в работе каналов и горутин
res равен nil, map изменяется конкурентно, а канал закрывается до завершения отправителей. Проще передать значения в main и дать ему единолично заполнить map.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
В этом упражнении вам нужно найти и устранить недочёты в представленном фрагменте кода, которые вызывают проблемы при работе с каналами и горутинами.
func main() {
m := map[int]int{}
wg := sync.WaitGroup{}
var res chan int
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
m[i] = i
res <- i
wg.Done()
}()
}
close(res)
wg.Wait()
}
Обратите внимание на корректность инициализации каналов, порядок закрытия и взаимодействие с синхронизацией горутин.
Ответ
res равен nil, map изменяется конкурентно, а канал закрывается до завершения отправителей. Проще передать значения в main и дать ему единолично заполнить map.
Такой вариант устраняет совместную запись и соблюдает порядок закрытия:
func main() {
m := make(map[int]int)
res := make(chan int)
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
res <- i
}(i)
}
go func() {
wg.Wait()
close(res)
}()
for value := range res {
m[value] = value
}
fmt.Println(m)
}
Нужны package main и импорты fmt, sync. Отправка в nil-канал блокируется, close(nil) вызывает panic. Закрывать канал должен владелец после завершения всех отправок; WaitGroup.Done лучше ставить в defer. Явная передача i также делает код независимым от старой семантики циклов.