Ich spiele etwas mit Go herum und habe ein Problem, das ich nicht lösen kann.
Der folgende Code ist der kleinstmögliche Code, der mein Problem reproduziert. Das Ziel des ursprünglichen Codes ist es, http Anfrage an Gououtines zu delegieren. Jede Goroutine macht ein paar schwere Bildberechnungen und soll darauf reagieren.
%Vor% Im Fall von go delegate(w)
bekomme ich keine Antwort, ohne go
it
klappt gut.
Kann jemand erklären, was vor sich geht? Vielen Dank!
ListenAndServe
startet bereits goroutines, um Ihre Handler-Funktion aufzurufen, also sollten Sie es nicht selbst tun.
Hier ist der Code der relevanten Funktionen der Paketquelle :
%Vor%Also sollte dein Code einfach
sein %Vor%Der Handler wird bereits von einer "äußeren" Goroutine (eine pro Anfrage) aufgerufen. Der Führer muss alles tun, was zu tun ist, z.B. schreibe eine vollständige Antwort, bevor sie zurückkehrt. Sie kehren "vorzeitig" b / c einer überflüssigen go-Anweisung zurück. Bitte versuchen Sie einfach den Körper von "delegate" in "handle" zu setzen und prüfen Sie, ob das etwas verbessert; -)
Manchmal kann der Go-Scheduler für Goroutines wirklich unbarmherzig sein. Das Problem ist das: Sie haben eine Anwendung und Sie laufen Routinen, also denkt der Scheduler: hey, ich könnte tatsächlich einige Optimierungen machen. Warum führe ich diese bestimmte Gorroutine nicht einfach später aus, um etwas CPU-Zeit zu sparen und die Anwendung reaktionsfähiger zu machen?
Dies ist der Fall: In Ihrem Code ist es nicht möglich, die Goroutine zu einem bestimmten Zeitpunkt zu beenden. Tatsächlich sagt die Go-Dokumentation folgendes:
Zum Beispiel in diesem Programm:
%Vor%die Aufgabe auf a folgt kein Synchronisationsereignis, also nicht garantiert von jeder anderen Goroutine beobachtet zu werden. In der Tat, ein aggressiver Compiler könnte die gesamte go-Anweisung löschen.
Wenn die Auswirkungen einer Goroutine von einer anderen Goroutine beobachtet werden müssen, Verwenden Sie einen Synchronisierungsmechanismus wie eine Sperre oder einen Kanal Kommunikation, um eine relative Reihenfolge zu etablieren.
Die Lösung für Ihr Problem besteht also darin, ein Synchronisationsereignis hinzuzufügen, z. mit einem Kanal:
Paket Haupt
%Vor%Von: Das Go Memory-Modell
Wie Sie bereits festgestellt haben, ist Ihr Beispiel derzeit irgendwie künstlich. Aber es gibt sicherlich Szenarien, in denen es sinnvoll ist, andere Goroutinen von einem http-Handler aus aufzurufen. Z.B. wenn Sie gleichzeitig schwere Berechnungen und HTTP-Streaming durchführen oder mehrere schwere Berechnungen gleichzeitig durchführen. Obwohl ich denke, dass Sie im letzteren Fall wahrscheinlich selbst einen Kanal für Synchronisationszwecke hinzugefügt hätten.
Tags und Links concurrency go