Пусть горутина закроет канал после отправки, а main сразу начнёт чтение. Ожидать отправителя до начала чтения небуферизированного канала нельзя.
Устранить panic при попытке записи в уже закрытый канал
Пусть горутина закроет канал после отправки, а main сразу начнёт чтение. Ожидать отправителя до начала чтения небуферизированного канала нельзя.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
В данном примере программа падает с panic: send on closed channel, потому что главный поток закрывает канал ch, не дождавшись завершения горутины, которая в это время пытается записать в канал. Требуется изменить поведение так, чтобы программа завершалась корректно, например, дождаться завершения горутины перед закрытием канала.
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan int)
go func() {
ch <- 1
}()
time.Sleep(time.Millisecond * 500)
close(ch)
for i := range ch {
fmt.Println(i)
}
time.Sleep(time.Millisecond * 100)
}
Ответ
Пусть горутина закроет канал после отправки, а main сразу начнёт чтение. Ожидать отправителя до начала чтения небуферизированного канала нельзя.
Исправленная программа:
package main
import "fmt"
func main() {
ch := make(chan int)
go func() {
defer close(ch)
ch <- 1
}()
for value := range ch {
fmt.Println(value)
}
}
Вывод — 1. Range ждёт значение и затем закрытие канала; Sleep не нужен. В исходнике отправитель ожидает получателя, а main закрывает канал прямо во время этого ожидания, что вызывает send on closed channel, если горутина продолжает исполняться. Порядок владения важнее временных задержек.