Канал, получаемый от только Println в обычной процедуре, генерирует исключение взаимоблокировки - PullRequest
0 голосов
/ 22 апреля 2019

У меня есть код, в котором я пытаюсь распечатать содержимое канала в программе с помощью fmt.Println. Вот упрощенная версия кода.

package main

import "fmt"
import "time"

func main() {
  ch := make(chan int)
  go fmt.Println(<-ch);
  ch<- 10;
  time.Sleep(time.Second * 10);
}

Когда я запускаю приведенный выше код, я получаю эту ошибку.

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.main()
        C:/cygwin64/home/vmadhusudana/go/channel.go:9 +0x67
exit status 2

Однако он работает нормально, когда я вызываю fmt.Println из функции

package main

import "fmt"
import "time"

func main() {
    ch := make(chan int)
    go func(){fmt.Println(<-ch)}();
    ch<- 10;
    time.Sleep(time.Second * 10);
}

Что здесь меняет?

Ответы [ 2 ]

3 голосов
/ 22 апреля 2019

В первой версии чтение канала выполняется из основной подпрограммы - отсюда тупик. Вторая версия, чтение выполняется из созданной go-рутины.

В основном это:

go fmt.Println(<-ch);

становится:

v := <-ch
go fmt.Println(v);

Поскольку параметры функции оцениваются до , это вызов.

P.S. Оператор defer ведет себя аналогично. Поэтому всегда используйте замыкание, если вы хотите, чтобы значение, переданное оператору go или defer, оценивалось во время выполнения.

2 голосов
/ 22 апреля 2019
// receive the value from channel firstly
// then create new goroutine to println
go fmt.Println(<-ch)

// receive channel in new goroutine 
go func(){fmt.Println(<-ch)}()

https://play.golang.org/p/xMyqd-Yr8_a

это поможет вам понять порядок исполнения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...