Meine Frage ergibt sich aus dem Versuch, einen Kanal zu lesen, wenn ich kann, oder schreibe es, wenn ich kann, mit einer select
-Anweisung.
Ich weiß, dass Kanäle wie make(chan bool, 1)
gepuffert sind, und ein Teil meiner Frage ist, was ist der Unterschied zwischen diesen und make(chan bool)
- was diese Seite sagt, ist das gleiche wie make(chan bool, 0)
--- was ist der Punkt eines Kanals, der 0 Werte hineinpassen kann?
Siehe Spielplatz A :
%Vor%Eine Ausgabe:
%Vor% (Das Entfernen des default
case führt zu einem Deadlock !!)
Sehen Sie sich Spielplatz B an:
%Vor%B Ausgabe:
%Vor%In meinem Fall ist B Ausgabe was ich will. Was gut sind ungepufferte Kanäle? Alle Beispiele, die ich auf golang.org sehe, benutzen sie, um ein Signal / einen Wert nach dem anderen zu senden (das ist alles was ich brauche) - aber wie in Spielplatz A wird der Kanal niemals gelesen oder geschrieben. Was vermisse ich hier in meinem Verständnis von Kanälen?
Was ist der Punkt eines Kanals, der 0 Werte hineinpassen kann?
Zunächst möchte ich darauf hinweisen, dass der zweite Parameter hier die Puffergröße bedeutet, also einfach ein Kanal ohne Puffer (un-gepufferter Kanal) ist.
Tatsächlich ist das der Grund, warum Ihr Problem erzeugt wird. Nicht gepufferte Kanäle sind nur beschreibbar, wenn jemand blockiert, um von ihr zu lesen, was bedeutet, dass Sie einige Coroutinen haben sollten, um damit zu arbeiten - anstatt dieser einzelnen.
Siehe auch Das Go Memory-Modell :
Ein Empfang von einem ungepufferten Kanal findet statt, bevor der Sendevorgang auf diesem Kanal abgeschlossen ist.
Ein ungepufferter Kanal bedeutet, dass Lese- und Schreibvorgänge vom und zum Kanal blockiert werden.
In einer select
-Anweisung:
default
ausgeführt, was in Ihrem Fall A geschieht. Unbuffered Kanäle (ohne Kapazität erstellt) blockiert den Absender, bis jemand von ihnen lesen kann, damit es wie erwartet funktioniert, sollten Sie zwei goroutines verwenden, um das Deadlock in demselben Thread zu vermeiden.
Zum Beispiel mit diesem Code: Ссылка
Es enthält auch einen Mechanismus für die Hauptfunktion, um zu erkennen, wenn beide Goroutinen beendet sind.
%Vor% Es wird nicht das alternative Lesen und Schreiben angezeigt, denn sobald send
in den Kanal schreibt, wird es blockiert, bevor es das "Schreiben" drucken kann, so dass die Ausführung zu recv
geht, das das empfängt Kanal und druckt "Lesen". Es wird versuchen, den Kanal erneut zu lesen, aber es wird blockiert und die Ausführung wird in send
verschoben. Nun kann send
das erste "Write" schreiben, an den Kanal senden (ohne zu blockieren, da jetzt ein Empfänger bereit ist) und das zweite "Write" schreiben. In jedem Fall ist dies nicht deterministisch und der Scheduler kann die Ausführung zu irgendeinem Zeitpunkt auf irgendeine andere laufende Routine (zumindest in der neuesten 1.2-Version) verschieben.