
Проблема здесь в том, что аргумент fmt.Println оценивается до запуска новой горутины, а не после. См. страницу Экскурсия по Го. Другими словами, ваш код (в основном) эквивалентен следующему:
val := <-c
go fmt.Println(val)
Это приводит к тупику основного потока, поскольку он ожидает, пока c создаст значение для передачи в fmt.Println в основной горутине. Поскольку горутина остается занятой, она никогда не достигает более поздней строки, где вы фактически отправляете значение в канал.
Вместо этого попробуйте это:
go func() { fmt.Println(<-c) }()
Здесь выполнение функции передается отдельной горутине перед вычислением <-c. Это позволяет основной горутине продолжать работу до тех пор, пока не достигнет c <- 32, чтобы предоставить значение для канала.
Вы создали блокирующий канал (без буфера). Он используется для выполнения «встречи», поэтому и отправитель, и получатель будут готовы обмениваться данными.
Параметры горутины оцениваются во время создания горутины, а это означает, что ваш код попытается прочитать из канала перед запуском нового потока.
Одно решение:
package main
import (
"fmt"
)
func main() {
c := make(chan int)
go func() {
fmt.Println(<-c)
}()
c <- 32
}
Go пытается прочитать значение вашей горутины перед ее созданием. Это эквивалентно:
go func(i int) {
for.Println(i)
}(<-c)
Чтобы иметь блок внутри горутины, вы должны прочитать канал внутри горутины, а не читать его как аргумент для горутины.
go func()
fmt.Println(<-c)
}
Таким образом, вы сначала вызываете свою горутину, а затем читаете канал.
С другой стороны, я не знаю, является ли результат программы случайным в зависимости от того, будет ли программа уничтожена до того, как можно будет вызвать печать.