2017-04-09 29 views
3
package main 

import "time" 

func main() { 
    chan_never_used := make(chan int, 10) 

    c := make(chan int, 10) 
    for { 
     select { 
     case <-time.After(time.Second): 
      c <- 0 
     case c <- <-chan_never_used: 
     } 

     println(<-c) 
    } 
} 

https://play.golang.org/p/7hZMdITecg在<code>fatal error: all goroutines are asleep - deadlock!</code>上time.After结果僵局

选择上述结果的代码。

但是,如果我改变一个行:

package main 

import "time" 

func main() { 
    chan_never_used := make(chan int, 10) 

    c := make(chan int, 10) 
    for { 
     select { 
     case <-time.After(time.Second): 
      c <- 0 
     case n := <-chan_never_used: // This line changed 
      c <- n     // Add this line 
     } 

     println(<-c) 
    } 
} 

它运作良好。

为什么第一个版本的代码会导致死锁,为什么这个改变会使代码工作?

回答

2

按照标准select statement包含一堆SendReceive声明。

在这种情况下,它是send语句。

发送陈述的定义为:

SendStmt = Channel "<-" Expression . 
Channel = Expression . 

看你的代码:

case c <- <-chan_never_used: 

Channel分数为c,则Expression分数<-chan_never_used

因此,发送声明的(可能)非阻塞的select语义不适用,因为它是阻塞的表达式。在应用发送语句语义之前,必须完全评估表达式部分。