2013-03-23 75 views
6

围绕Go的渠道和例程玩耍我遇到了一个奇怪的行为,我希望有人能够解释。在goroutine中进行选择评估所有其他语句

下面是一个简短的程序,它应该将字符串通过通道发送到在单独的goroutine中运行的“侦听器”(select语句),从而将两个字符串打印到stdout。

package main 

import (
    "fmt" 
    "time" 
) 

func main() { 
    a := make(chan string) 

    go func() { 
     for { 
      select { 
      case <-a: 
       fmt.Print(<-a) 
      } 
     } 
    }() 

    a <- "Hello1\n" 
    a <- "Hello2\n" 
    a <- "Hello3\n" 
    a <- "Hello4\n"   
    time.Sleep(time.Second) 
} 

使用

go func() { 
    for s := range a { 
     fmt.Print(s) 
    } 
}() 

// or even simpler 

go func() { 
    for { 
     fmt.Print(<-a) 
    } 
}() 

按预期工作。但是,使用select语句运行最上面的代码片段会产生以下输出:

Hello2 
Hello4 

即只打印每隔一个其他语句。这是什么魔法?

回答

12

在最上面的代码片段中,您将为每个循环从通道中提取两个值。一个在select语句中,另一个在print语句中。

变化

 select { 
     case <-a: 
      fmt.Print(<-a) 

 select { 
     case val := <-a: 
      fmt.Print(val) 

http://play.golang.org/p/KIADcwkoKs

+0

谢谢,它是有道理的。我会放弃它;) – 0sh 2013-03-24 12:41:21

7
<-a 

获取来自信道的值,破坏性。所以在你的代码中,你会得到两个值,一个在select语句中,一个在打印。 select语句中收到的一个没有绑定到任何变量,因此丢失。

尝试

select { 
    case val := <-a: 
     fmt.Print(val) 

代替,得到只有一个值,将其绑定到变量val,并打印出来。