2013-03-23 82 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,並打印出來。