2015-11-08 172 views
3

下面这段代码为什么会产生错误?这段代码为什么会产生一个错误?

func main() { 

    messages := make(chan string) 

    messages <- "test" //line 16 

    fmt.Println(<-messages) 

} 

生成以下错误。

fatal error: all goroutines are asleep - deadlock! 
goroutine 1 [chan send]: 
main.main() 
    /tmp/sandbox994400718/main.go:16 +0x80 

将值发送到通道,并在下一行中接收值。技术上它应该工作。

回答

0

我现在已经学到了很多渠道,现在我可以回答这个问题。

在管线16时消息“测试”是由主螺纹(够程)的执行暂停和运行时查找,其已准备好从信道信息接收值其他够程发送到信道。由于没有其他通道,运行时会引发死锁消息的恐慌。这是一个死锁的经典例子。

要解决这个问题有可以做两件事情。

1)使用缓冲通道马特建议的答案(之一)。

2)否则具有发送到信道或信道从在一去例程接收的发言。

func main() { 

    messages := make(chan string) 

    go func() { 
     messages <- "test" //line 16 
    }() 
    fmt.Println(<-messages) 

} 

所以从这个基本拿走的题是,

1)通道只能用来够程即之间的通信,当你发送一个够程信道只能在其他的goroutine收到它不一样。

2)当数据以的goroutine直到该数据被从在另一个的goroutine相同的信道接收到的goroutine的流量/执行暂停发送给信道。

4

通道可以是缓冲无缓冲。一个缓冲通道可以在内部存储多个项目,但是当你向缓冲通道添加一些项目时,添加项目的goroutine只能在另一个goroutine删除项目时继续。没有地方“离开”物品,它必须直接传递给另一个goroutine,并且第一个goroutine将等到另一个人从其中取出物品。

这就是你的代码中发生的事情。当您使用make创建频道时,如果您未指定容量作为第二个参数,则会获得无缓冲的频道。要创建缓冲通道,请将第二个参数传递给make,e.g

messages := make(chan string, 1) // could be larger than 1 if you want 

这使得够程的项目(在这种情况下string)添加到频道,在那里将可在另一够程试图在未来的渠道得到一个项目,原来的够程然后可以继续处理。

+0

我得到的,但怎么就是这个例子http://play.golang.org/p/2ox5ObgKIP不需要缓冲。 – nJoshi

+3

@nJoshi在那个例子中有_two_ goroutines。 goroutine以'go func()...'开始,将字符串传递给通道(并等待),主要goroutine检索它(并允许另一个继续)。 – matt

相关问题