Event-driven-Muster in golang
Ich bin mit golang zu implementieren eine einfache event-driven-Arbeiter. Es ist so:
go func() {
for {
select {
case data := <-ch:
time.Sleep(1)
someGlobalMap[data.key] = data.value
}
}
}()
Und die main-Funktion erstellen mehrere goroutines, und jeder von Ihnen wird nicht etwas, wie:
ch <- data
fmt.Println(someGlobalMap[data.key])
Wie Sie sehen können, dass, weil meine Arbeiter brauchen einige Zeit, um die Arbeit zu tun, ich habe null-Ergebnis in meiner main-Funktion.Wie kann ich diesen workflow richtig?
- Die Karte gelesen werden soll, synchronisiert mit dem schreiben goroutines. Versuchen Sie
ch <- data
als ein weiterer Fall in der select-Klausel.
Du musst angemeldet sein, um einen Kommentar abzugeben.
BEARBEITEN: vielleicht habe ich deine Frage falsch verstanden, ich sehe, dass Sie erwähnen, dass "main" beginnen viele Produzent goroutines. Ich dachte, es war viele Verbraucher goroutines und einem einzigen Hersteller. Verlassen Sie die Antwort hier im Fall kann es sinnvoll sein, für andere auf, die für das Muster, aber die Kugel Punkte noch für Ihren Fall.
Also, wenn ich das richtig verstehe ist dein use-case ist, können Sie nicht erwarten, um zu senden auf einem Kanal, und Lesen Sie die Ergebnisse sofort nach. Sie wissen nicht, Wann der worker-Prozess senden, müssen Sie die Kommunikation zwischen goroutines, und dass geschieht mit den Kanälen. Angenommen, nur den Aufruf einer Funktion mit Rückgabewert funktioniert nicht in Ihrem Szenario, wenn Sie wirklich brauchen, um zu senden zu einem Arbeiter, dann blockieren Sie bis Sie das Ergebnis hat, könnten Sie schicken ein Kanal als Teil der Datenstruktur, und block-erhalten Sie nach dem senden, also:
Aber Sie sollten wahrscheinlich versuchen zu brechen, der das Werk als eine Reihe von voneinander unabhängigen Schritten statt, siehe den blog-post, den ich verlinkt in der ursprünglichen Antwort.
Ursprüngliche Antwort, wo ich dachte, es war eine einzelne Produzent - mehrere Verbraucher/Arbeitnehmer Muster:
Dies ist ein gemeinsames Muster für die Go goroutines und Kanälen Semantik sehr gut geeignet sind. Es gibt ein paar Dinge, die Sie benötigen, im Auge zu behalten:
Der main-Funktion wird nicht automatisch warten goroutines zu beenden. Wenn es nichts anderes zu tun in der Haupt -, dann wird das Programm beendet und Sie nicht über Ihre Ergebnisse.
Die Globale Karte, die Sie verwenden, ist nicht thread-safe. Müssen Sie synchronisieren, Zugang über ein mutex, aber es gibt einen besseren Weg - mit einem output-Kanal für die Ergebnisse, die bereits synchronisiert.
Können Sie mithilfe einer for..über einen Kanal, und Sie können sicher teilen sich ein Kanal zwischen mehreren goroutines. Wie wir sehen werden, macht, dass dieses Muster sehr elegant, zu schreiben.
Spielplatz: https://play.golang.org/p/WqyZfwldqp
Mehr auf Gehen Rohrleitungen und Parallelität-Muster, Einführung, Fehlerbehandlung, die vorzeitige Kündigung, etc.: https://blog.golang.org/pipelines
Kommentierte code für die Einsatz-Fall, die Sie erwähnen:
In real-life-Szenarien, wo die Menge der Arbeit ist nicht bekannt, vor der Zeit, die Schließung der in-Kanal kann sich z.B. ein SIGINT-signal. Nur stellen Sie sicher, dass keine code-Pfad schicken kann funktionieren, nachdem der Kanal geschlossen war, denn das würde die Panik.