2012-04-14 7 views
4

Als ich versuchte zu drucken: goroutine Kanäle - der Wert der Sende Anweisung

fmt.Println(c <- x)
direkt vor der for-Schleife in dem Codeblock unten, um zu sehen, was „c < - x“ zu bewerten wäre, hätte es die Fehlermeldung:

./select.go:7: send-Anweisung c < - x wird als Wert verwendet; Verwendung auswählen für nicht blockierenden Send

Wird "c < - x" als wahr ausgewertet, wenn der Sendevorgang erfolgreich war? Und warum lässt Go nur den Wert der send-Anweisung (aka Wert von "c < - x") in case-Anweisungen innerhalb einer select-Anweisung verwenden?

func fibonacci(c, quit chan int) { 
     x, y := 1, 1 

     for { 
      select { 
      case c <- x: 
       x, y = y, x + y 
      case <-quit: 
       fmt.Println("quit") 
       return 
      } 
     } 
    } 

Danke

Antwort

8

Es ist wahr, c <- x eine Aussage ist und keinen Wert hat.

Sie könnten select mit switch verwirren. Switch funktioniert, indem er erkennt, welcher Case-Ausdruck mit "true" übereinstimmt oder als "true" interpretiert. Auf der anderen Seite sucht Select nach Fällen, die nicht blockiert sind, wählt eine davon aus, um fortzufahren, und führt dann die Anweisungen im Fallblock aus.

Also nein, c <- x wird nicht ausgewertet, wenn der Sendevorgang erfolgreich war. Stattdessen wird einfach die Anweisung des Fallblocks x, y = y, x + y ausgeführt. Es gibt kein Ergebnis eines Sends, keinen wahren Wert, der irgendwo gespeichert wird.

Möglicherweise haben Sie gelesen, dass für eine empfangen Operation eine Variable mit einer kurzen Deklaration zugeordnet ist nur im Rahmen des Fall blockieren. Dies ist richtig (obwohl es in den Fällen der obigen SELECT-Anweisung keine kurzen Deklarationen gibt.) Wenn Sie einen Fall hatten, in dem Sie nach dem Beenden des Case-Blocks einen empfangenen Wert erhalten wollten, würden Sie eine einfache Zuweisung und keine kurze Deklaration verwenden.

Oblig: the language spec on the select statement. Es ist wirklich sehr gut lesbar.

+0

Ich mache manchmal das gleiche versehentlich, wenn mein Python-Gehirn mit meinen Go-Zielen in Konflikt gerät und ich versuche, einen "Callback" als "Callback (structInstance.method)" zu übergeben – jdi