2013-03-23 8 views
6

Zabawa z kanałami i procedurami Go, natknąłem się na dziwne zachowanie, miałem nadzieję, że ktoś może wyjaśnić.Wybrać w goroutine ocenia każde inne stwierdzenie

Poniżej znajduje się krótki program, który ma wydrukować kilka ciągów na standardowe wyjście, wysyłając ciągi przez kanał do "słuchacza" (instrukcja SELECT) działającego w oddzielnym gorylerze.

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) 
} 

Korzystanie

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

// or even simpler 

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

działa zgodnie z oczekiwaniami. Jednak działa szczytowego fragment z instrukcji wyboru daje następujący wynik:

Hello2 
Hello4 

czyli każdy inny rachunek jest drukowana tylko. Co to za magia?

Odpowiedz

12

W najwyższym fragmencie kodu pobierasz dwie wartości z kanału dla każdej pętli. Jeden w instrukcji select i jeden w poleceniu print.

Zmień

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

Aby

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

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

+0

Dzięki, to ma sens. Dam ci szansę;) – 0sh

7
<-a 

pobiera wartość z kanału, destrukcyjnie. W kodzie otrzymasz dwie wartości, jedną w instrukcji select i jedną do wydrukowania. Ten otrzymany w instrukcji select nie jest powiązany z żadną zmienną i dlatego zostaje utracony.

Spróbuj

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

zamiast dostać tylko jedną wartość, przypisz go do zmiennej val, a następnie wydrukować go.