Einer der beliebtesten Aspekte der Programmiersprache Go ist ihre erstklassige Unterstützung für die Fähigkeit eines Computers, viele Aufgaben gleichzeitig auszuführen. Die Fähigkeit, Code gleichzeitig auszuführen, wird in der Programmierung immer wichtiger, da Computer von der schnelleren Ausführung eines einzelnen Codeflusses zur gleichzeitigen Ausführung vieler Datenströme übergehen. Um Programme schneller ausführen zu können, müssen Programmierer sie so gestalten, dass sie gleichzeitig ausgeführt werden können, so dass jedes gleichzeitige Element des Systems unabhängig von den anderen ausgeführt werden kann.
Zwei Funktionalitäten von Go, Goroutines, und Channels erleichtern die Gleichzeitigkeit, wenn sie zusammen eingesetzt werden. Goroutines bietet den grundlegenden Urtyp für diese Fähigkeit. Goroutines ist weniger kostspielig in Bezug auf Speicherplatz, Inter-Thread-Interaktion und Netzwerkkonnektivität. Sie haben auch eine bessere Startzeit als Threads, die von vielen Programmiersprachen unterstützt werden. Im Wesentlichen bezieht sich Go auf Goroutines als das, was Java und andere Programmiersprachen als Threads bezeichnen.
Was sind Goroutines?
Eine Goroutine ist eine einfache Thread-Implementierung in Golang, die gleichzeitig mit dem Rest des Programms abläuft. Goroutines ist erschwinglich, da die Kosten für die Erstellung einer Goroutine extrem niedrig sind, wenn sie einem Standard-Thread ähnelt. Daher werden sie in Go ausgiebig für die nebenläufige Programmierung verwendet. Jedes Programm besteht aus mindestens einer einzigen Goroutine, die als Hauptgoroutine bezeichnet wird. Die Haupt-Goroutine steuert alle anderen Goroutinen; wenn also die Haupt-Goroutine beendet wird, tun dies auch alle anderen Goroutinen im Skript. Die Goroutine ist immer im Hintergrund aktiv.
Beispiel: Hier ein Beispiel: Sie schreiben etwas in Ihr Notizbuch und bekommen Hunger; Sie machen eine Pause und holen sich etwas zu essen. Dann beginnen Sie wieder zu schreiben. Sie nehmen nun zwei Aufgaben (Schreiben und Essen) in einem Zeitfenster wahr, das als gleichzeitige Beschäftigung gilt. Es ist zu betonen, dass diese beiden Aufgaben (Schreiben und Essen) immer noch gleichzeitig erledigt werden müssen. Wenn Aufgaben gleichzeitig erledigt werden, spricht man von Parallelität (stellen Sie sich vor, Sie benutzen Ihr Mobiltelefon, während Sie Chips mampfen). Gleichzeitigkeit bedeutet, mit vielen Dingen gleichzeitig zu interagieren. Parallelität (viele Dinge gleichzeitig ausführen) ist eine Unterklasse davon (muss nicht gleichzeitig ausgeführt werden) mit einem gewissen Zeitplan.
Wir können eine Goroutine hinzufügen, indem wir das Schlüsselwort go auf den Funktionsaufruf anwenden. Sobald wir das Schlüsselwort go auf den Funktionsaufruf anwenden, setzen wir die Gleichzeitigkeit auf die Leistung. Doch zunächst wollen wir die Auswirkungen der Anwendung des Schlüsselworts go auf die Ausführung ermitteln. Nehmen wir an, es gibt zwei Goroutinen in einem Programm. Der Text "package main import" wird der Einstieg in das Programm sein. In Go ist ein package main import eine deklarative Importanweisung. Die Haupt-Goroutine (first goroutine) ist impliziert. Wenn wir go (f) ausführen, wird die zweite Goroutine gebildet (0). Normalerweise führt unsere Software jeden Befehl in der primären Funktion aus, wenn wir eine Funktion ausführen, bevor wir mit der nächsten Zeile fortfahren.
Mit einer Goroutine können wir die Prozedur schnell ausführen, bevor wir mit dem nächsten Schritt fortfahren. Deshalb wurde eine scanln-Methode hinzugefügt; andernfalls würde der Code enden, bevor alle Zahlen angezeigt werden. Goroutines ist einfach zu erstellen und kann in großer Anzahl erstellt werden. Wenn diese Software ausgeführt wird, werden Sie feststellen, dass die Goroutinen eher sequentiell als gleichzeitig zu arbeiten scheinen.
Vorteile von Goroutines gegenüber Threads
Goroutines kosten wenig
Goroutines sind weniger teuer als andere Prozesse. Die Größe der Masse beträgt nur wenige Kilobyte, und sie kann sich je nach den Anforderungen des Programms vergrößern oder verkleinern, im Gegensatz zu Threads, deren Stapelgröße festgelegt werden muss und permanent ist.
Es gibt gemultiplexte Goroutines
Es gibt nur sehr wenige Betriebssystem-Threads, mit denen sie gemultiplext sind. In einem Programm mit Hunderten von Goroutinen kann es nur einen Prozess geben. Die übrigen Goroutinen werden an den neuen Betriebssystemprozess übergeben. Angenommen, eine der Goroutinen in diesem Prozess hängt fest, zum Beispiel, wenn sie einen Benutzereingriff verlangt. Die Laufzeitumgebung verwaltet alle diese Vorgänge, und wir Entwickler erhalten eine klare API, mit der wir gleichzeitig arbeiten können, während wir von diesen subtilen Feinheiten abgeschirmt sind.
Goroutines über Kanäle kommunizieren
Goroutines unter Verwendung von Kanälen kommunizieren. Sie sollen verhindern, dass es zu Wettlaufsituationen kommt, wenn sie sich relevanten Speicher teilen. Kanäle können mit einem Kanal verglichen werden, den Goroutinen zur Interaktion nutzen.
Was sind Kanäle?
Zwei Goroutinen können miteinander interagieren und ihre Operationen über Kanäle koordinieren. Diese Software gibt ständig "ping" aus. Um eine Kanalform zu bezeichnen, wird das Präfix "chan" von den auf dem Kanal übertragenen Elementen begleitet." In diesem Fall handelt es sich um Zeichenketten. Auf dem Kanal werden die Nachrichten mit dem Operator gesendet und empfangen. Das Präfix "ping" bezieht sich auf das Senden von "ping".
Ein Kanal wird verwendet, um die beiden Goroutinen synchron zu halten. Bevor der Router versucht, eine Nachricht über den Kanal zu senden, wartet er, bis der Drucker bereit ist, sie anzunehmen. Der Begriff hierfür ist Inhibition. Bei der Erstellung eines Kanals kann ein zweiter Parameter für die make-Funktion verwendet werden: c:= make (chan int, 1)
Die Richtung des Kanals
Wir können die Ausrichtung eines Kanalformulars definieren und es entweder für den Empfang oder das Senden parametrieren. Das Vorzeichen der Methode Pinger kann z.B. folgendermaßen geändert werden:
func pinger(c chan<- string)
C kann nur noch gesendet werden. Das Empfangen von c führt zu einem Codefehler. In ähnlicher Weise können wir die Ausgabe zu ändern:
func printer(c string -chan)
Für einen Halbkanal gelten diese Einschränkungen nicht. Ein bidirektionaler Kanal kann an eine Prozedur übergeben werden, die nur Sende- oder nur Empfangskanäle akzeptiert, aber nicht andersherum.
Wie erstellt man eine Goroutine?
Die Methode zum Starten einer Goroutine ist ganz einfach. Wenden Sie das Schlüsselwort "go" auf den Funktionsaufruf an, um eine Goroutine zu erstellen, die gleichzeitig ausgeführt wird. Hier werden wir eine Goroutine erstellen. Nehmen wir an, wir haben ein Programm, das zwei Funktionen enthält: die eine ist eine Begrüßungsfunktion und die andere ist die Hauptfunktion.
Wenn wir eine neue Goroutine erstellen, wird der welcome ()-Code neben der main()-Funktion ausgeführt. Wenn Sie dieses Programm ausführen, werden Sie überrascht sein. Dieses Programm zeigt lediglich den Text der Hauptfunktion. Was ist mit der ersten Goroutine oder neuen Goroutine passiert, die wir gestartet haben? Um zu verstehen, warum dies geschieht, müssen wir zunächst die beiden Hauptmerkmale von Goroutinen kennen.
- Die Goroutine-Funktion reagiert sofort, wenn wir eine neue Goroutine erstellen. Abgesehen von Funktionen ist die Verwaltung nicht auf die Goroutine angewiesen, wartet also nicht darauf, dass sie ihre Ausführung beendet. Die Ausführung wird an den folgenden Codeblock nach der Goroutine-Funktion übergeben. Aus diesem Grund werden die von der Goroutine übergebenen Parameter nicht beachtet.
- Alle zusätzlichen Goroutinen sollten gleichzeitig mit der Hauptgoroutine ausgeführt werden. Wenn die Haupt-Goroutine fehlschlägt, wird das Programm beendet, und es werden keine weiteren Goroutinen ausgeführt.
Sie verstehen nun, warum unser Code nicht funktioniert hat. Nach dem Aufruf von go welcome() wurde die Kontrolle an die folgende Codezeile übergeben, bevor auf die Beendigung der hallo-Goroutine gewartet und die Hauptfunktion ausgegeben wurde. Die Haupt-Goroutine starb, weil es kein Skript gab, das ausgeführt werden konnte, wodurch die Hallo-Goroutine nicht ausgeführt werden konnte.
Wir riefen die sleep-Technik (time.sleep(1 * time.second)) auf, um die Goroutine für 1 Sekunde zu pausieren. Die Funktion to go welcome () hat nun genügend Zeit, um vor dem Beenden der Haupt-Goroutine ausgeführt zu werden. Diese Software schreibt zunächst das "welcome goroutine" und wartet dann eine Sekunde, bevor sie die Hauptfunktion ausgibt. Wir verwenden die sleep-Technik in der Haupt-Goroutine, um sie für einen Moment anzuhalten, damit die anderen Goroutinen fertig werden können.
Mehrere Programme erstellen Goroutines
Wir werden ein weiteres Programm starten, um mehrere Goroutinen zu erstellen. Wir können zunächst zwei Goroutinen erstellen, die parallel ausgeführt werden sollen. Diese beiden Goroutinen sind die Zahlen-Goroutine [go numbers()] und die Alphabet-Goroutine [go alphabets ()].
Die Zahlen-Goroutine verweilt 250 ms, bevor sie die 1 ausgibt, pausiert erneut, bevor sie die 2 ausgibt, und so weiter, bis sie die 5 erzeugt. In ähnlicher Weise zeigt die alphanumerische Goroutine die Buchstaben von a bis e an und wartet dann 400 Millisekunden. Schließlich erstellt die primäre Goroutine die Ganzzahlen und alphanumerischen Zeichen, macht eine kurze Pause und beendet dann die Haupt-Goroutine.
Häufige Fehler bei der gleichzeitigen Programmierung
- Fehlende Synchronisationen, wenn dies erforderlich ist
- Verwendung von Time. Sleep-Aufrufe zur Durchführung von Synchronisationen
- Goroutinen mit Kopierwerten der Typen im Standard-Sync-Paket baumeln lassen
- Aufrufen der sync
- Waitgroup
- Methode an falschen Stellen hinzufügen
- Kanäle als Close-Morrow-Kanäle verwenden, nicht von der letzten funktionierenden Sender-Goroutine
Fazit
In diesem Artikel haben wir ein Programm entwickelt, das das Schlüsselwort go verwendet, um eine Goroutine und mehrere Goroutinen zu starten, die gleichzeitig Ganzzahlen ausgeben. Nach dem Start des Programms haben wir einen neuen Kanal eingerichtet, mit dem wir dann in einer Goroutine Zahlen erzeugt und an eine andere Goroutine weitergegeben haben, damit sie auf dem Bildschirm angezeigt werden können. Als letzte Demonstration, wie Sie eine Goroutine starten können, um Ihre Anwendungen auf Mehrkernsystemen zu beschleunigen, haben Sie gleichzeitig mehrere "druckende" Goroutinen gestartet.
Wie wir wissen, sind Goroutinen ein Mittel, um Aufgaben schneller und effizienter auszuführen. Dies ist eines der von AppMaster angebotenen Einsatzverfahren, um die Funktionalität Ihrer Anwendung zu verbessern. Mit AppMaster können auch Personen mit geringen oder gar keinen Programmierkenntnissen Aufgaben erledigen, die durch manuelle Programmierung nur schwer zu bewältigen wären.
AppMaster ist eine no-code Plattform, mit der man sowohl mobile und Web-Anwendungen als auch ein Backend erstellen kann. Ein interessanter Fakt: AppMaster erstellt ein Backend mit Go mit 22.000 Zeilen pro Sekunde und Sie können auf den Quellcode zugreifen.