通道仅从Println中的go例程中接收到通道会引发死锁异常

时间:2019-04-22 06:55:05

标签: go

我有一些代码,我尝试使用fmt.Println在goroutine中打印通道的内容。这是简化的代码。

ProcessImpl

运行上面的代码时,出现此错误。

package main

import "fmt"
import "time"

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

但是,当我从函数调用fmt.Println时,效果很好

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

这有什么不同?

2 个答案:

答案 0 :(得分:3)

在第一个版本中,通道读取是从主例程执行的-因此发生了死锁。 第二个版本是从创建的例程中读取的。

基本上是这样:

go fmt.Println(<-ch);

成为:

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

由于函数的参数在调用之前 进行评估。

P.S。 defer语句的行为类似。因此,如果要在“运行时”对传递给go-routine或defer语句的值进行求值,请始终使用闭包。

答案 1 :(得分:2)

// 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

这将帮助您了解执行程序的顺序。