2017-06-01 4 views
2

Betrachten Sie das Spielzeugbeispiel unten. Der Code funktioniert tadellos, aber wenn Sie die 2 Linien austauschen, die als replace markiert werden, gibt es einen Deadlock. Gibt es einen besseren Weg, mit einer solchen Situation umzugehen, wenn Sie eine unterschiedliche Anzahl von Sends und Empfängern haben?Golang Kanäle, die sich mit Senden befassen! = Erhalten

package main 

import "fmt" 
import "strconv" 

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

    go func() { 
     for i := 0; i < 2; i++ { 
      go func(i int) { 
       fmt.Println(<-a) 
       b <- strconv.Itoa(i) + "b" // replace 
       a <- strconv.Itoa(i) + "a" // replace 
      }(i) 
     } 
    }() 

    a <- "0" 
    for i := 0; i < 2; i++ { 
     fmt.Println(<-b) 
    } 
} 

EDIT: eine select-Anweisung verwendet wird, gibt es eine Chance, dass a wird durch die Auswahl und es gibt immer noch keine Möglichkeit, einen Stillstand zu verhindern abgeholt, weil die goroutines nicht

ausführen kann
package main 

import "fmt" 
import "strconv" 

func main() { 
    a := make(chan string) 
    b := make(chan string) 
    c := make(chan bool) 
    cancel := make(chan bool) 

    go func() { 
     for i := 0; i < 2; i++ { 
      go func(i int) { 
       fmt.Println(<-a) 
       b <- strconv.Itoa(i) + "b" // replace 
       a <- strconv.Itoa(i) + "a" // replace 
       c <- true 
      }(i) 
     } 
    }() 

    go func() { 
     <-c 
     <-c 
     cancel <- true 
    }() 

    a <- "0" 

loop: 
    for { 
     select { 
     case ain := <-a: 
      fmt.Println("select", ain) 
     case bin := <-b: 
      fmt.Println("select", bin) 
     case <-cancel: 
      break loop 
     } 
    } 
} 

Antwort

2

Verwendung wählen :

Dieses Beispiel wird sitzen und für ein Element blockieren, das auf a oder b-Kanälen gesendet wird.

Optional setze ich normalerweise ein Cancel Token oder ein Timeout.

Ihr ursprünglicher Code blockiert auf dem Switch, weil Sie auf B gesendet haben, wo Sie nur auf A. Golang gehört haben, dass Sie auf dem Kanal hören, BEVOR Sie überhaupt senden. Dies ist das Muster für mehrere Kanäle, ohne zu wissen, welches Sie zuerst erhalten werden.

+0

Wo schlägst du vor, dass ich das ... Mein Beispiel ist nur eine Vereinfachung, '<-a' und' <-b' müssen sein, wo ich sie in den Code einfüge. Denke nicht, dass ich ihre Standorte ändern kann. – tushar

+0

Mit deinem Code aktualisiert. Ihr Originalcode macht keinen Sinn, da kein aktuelles Programm so geschrieben werden kann. Sie wollen immer den Empfänger des Kanals sperren, Punkt. Wenn Sie mehr als einen Kanal haben, benötigen Sie ein 'select', um an der ersten Eingabe zu blockieren. Wenn Sie mehrere Eingaben haben, wickeln Sie die Auswahl in eine for-Schleife. – eduncan911

+0

Klingt wie B ist der Fall "Abbrechen" in meinem Beispiel. ;) – eduncan911

Verwandte Themen