Go Channels Tutorial

In diesem Tutorial werden wir uns ansehen, wie Sie Kanäle in Ihren Go-basierten Anwendungen verwenden können.

Kanäle sind Pipes, die zwischen goroutines innerhalb Ihrer Go basedapplications , die die Kommunikation und anschließend die Übergabe von Werten an und von Variablen ermöglichen.

Sie sind unglaublich praktisch und können Ihnen helfen, unglaublich leistungsstarke, hochgradig gleichzeitige Anwendungen in Go mit minimalem Aufwand im Vergleich zu anderen Programmiersprachen zu erstellen. Dies war keineswegs ein Zufall, bei der Gestaltung der Sprache entschieden sich die Kernentwickler, dass sie Parallelität innerhalb ihrer Sprache wollten, um ein erstklassiger Bürger zu sein und es so einfach wie möglich zu machen, ohne zu weit zu gehen und Entwicklern nicht die Freiheit zu geben, in der sie arbeiten können.

Die Fähigkeit, gleichzeitige Systeme so einfach zu erstellen, hat mich überhaupt erst zur Sprache gebracht, und ich muss sagen, es war bisher ein absolutes Highlight.

Hinweis – Ich würde empfehlen, einen Blick auf mein anderes Tutorial über Goroutinen zu werfen, wenn Sie mehr über Goroutinen erfahren möchten.

Am Ende dieses Tutorials werden Sie:

  • Haben Sie ein solides Verständnis für die Theorie hinter channels
  • In der Lage sein, einfache gleichzeitige Go-Anwendungen zu erstellen, die Channels verwenden

Voraussetzungen

Um dieses Tutorial abzuschließen, müssen Sie die folgenden Voraussetzungen erfüllt haben:

  • Sie müssen Go auf Ihrem Computer installiert haben.

Video-Tutorial

Wenn Sie möchten, ist dieses Tutorial im Videoformat verfügbar.

Die Theorie

Die Idee von Kanälen ist nichts Neues, da diese Konzepte, wie viele von Go’s Concurrencyfeatures, von Hoare’s Communicating Sequential Processes (1978), kurz CSP, und sogar von Dijkstras guarded Commands (1975) übernommen wurden.

Die Entwickler von Go haben es sich jedoch zur Aufgabe gemacht, diese Konzepte so einfach wie möglich darzustellen, damit Programmierer bessere, korrektere und hochgradig gleichzeitige Anwendungen erstellen können.

Ein einfaches Beispiel

Lassen Sie uns zunächst sehen, wie wir ein wirklich einfaches Beispiel dafür erstellen könnendas funktioniert in Go. Wir erstellen zuerst eine Funktion, die weggeht und einen willkürlichen Zufallswert berechnet und an eine Kanalvariable namens zurückgibtvalues:

haupt.gehen

Lassen Sie uns disect, was hier passiert ist. In unserer main() Funktion haben wirvalues := make(chan int) aufgerufen, dieser Aufruf hat effektiv unseren neuen Kanal erstellt, sodass wir ihn anschließend in unserer CalculateValue Goroutine verwenden können.

Hinweis – Wir haben make beim Instanziieren unseres values Kanals verwendet, da Kanäle wie Maps und Slices vor der Verwendung erstellt werden müssen.

Nachdem wir den Kanal erstellt hatten, haben wir defer close(values) aufgerufen, wodurch das Schließen unseres Kanals bis zum Ende der Ausführung unserer main() -Funktion verschoben wurde. Dies wird normalerweise als Best Practice angesehen, um sicherzustellen, dass wir alles selbst aufräumen.

Nach unserem Aufruf von defer starten wir unsere einzelne Goroutine:CalculateValue(values) Übergeben unseren neu erstellten values -Kanal als Parameter. Innerhalb unserer CalculateValue -Funktion berechnen wir einen einzelnen Zufallswert zwischen 1-10, drucken diesen aus und senden diesen Wert dann an unseren values -Kanal, indem wir values <- value aufrufen.

Wir springen zurück in unsere main() -Funktion und rufen dann value := <-values auf, das einen Wert von unserem values -Kanal empfängt.

Hinweis – Beachten Sie, dass dieses Programm nicht sofort beendet wird, wenn wir es ausführen. Dies liegt daran, dass das Senden an und Empfangen von einem Kanal blockiert wird. Unsere main() -Funktion blockiert, bis sie einen Wert von ourchannel erhält.

Bei der Ausführung dieses Codes sollte die Ausgabe ungefähr so aussehen:

$ go run main.goGo Channel TutorialCalculated Random Value: {} 77

Zusammenfassung:

myChannel := make(chan int) – erstellt myChannel, das ein Kanal vom Typ istint

channel <- value – sendet einen Wert an einen Kanal

value := <- channel – empfängt einen Wert von einem Kanal

Das Instanziieren und Verwenden von Kanälen in Ihren Go-Programmen sieht also bisher ziemlich geradlinig aus, aber was ist mit komplexeren Szenarien?

Ungepufferte Kanäle

Die Verwendung eines herkömmlichen channel in Ihren Goroutinen kann manchmal zu Problemen mit einem Verhalten führen, das Sie möglicherweise nicht ganz erwarten. Bei herkömmlichenunbuffered -Kanälen wird diese Goroutine, wenn eine Goroutine einen Wert an diesen Kanal sendet, anschließend blockiert, bis der Wert vom Kanal empfangen wird.

Sehen wir uns das an einem realen Beispiel an. Wenn wir uns den folgenden Code ansehen, ist er sehrähnlich dem Code, den wir zuvor hatten. Wir haben jedoch unsereCalculateValue() -Funktion erweitert, um ein fmt.Println auszuführen, nachdem es seinen zufällig berechneten Wert an den Kanal gesendet hat.

In unserer main() -Funktion haben wir einen zweiten Aufruf zugo CalculateValue(valueChannel) hinzugefügt, sodass wir erwarten sollten, dass 2 Werte sehr schnell hintereinander an thischannel gesendet werden.

Haupt.go

Wenn Sie dies ausführen, sollten Sie jedoch sehen, dass nur die finalprint-Anweisung unserer ersten Goroutinen tatsächlich ausgeführt wird:

go run main.goGo Channel TutorialCalculated Random Value: {} 1Calculated Random Value: {} 71Only Executes after another goroutine performs a receive on the channel

Der Grund dafür ist, dass unser Aufruf von c <- value in unserer zweiten Routine blockiert wurde und anschließend die Funktion main() ihre Ausführung abschließt, bevor unsere zweite goroutine die Möglichkeit erhält, ihre eigene Ausführung abzuschließen.

Gepufferte Kanäle

Die Möglichkeit, dieses Blockierungsverhalten zu umgehen, besteht darin, einen sogenannten gepufferten Kanal zu verwenden. Diese gepufferten Kanäle sind im Wesentlichen Warteschlangen einer bestimmten Größe, die für die goroutineübergreifende Kommunikation verwendet werden können. Um einen gepufferten Kanal im Gegensatz zu einem ungepufferten Kanal zu erstellen, liefern wir unserem Befehl make ein capacityargument:

bufferedChannel := make(chan int, 3)

Wenn Sie dies in einen gepufferten Kanal ändern, wird unsere Sendeoperation c <- value nur innerhalb unserer Goroutinen blockiert, falls der Kanal voll ist.

Lassen Sie uns unser bestehendes Programm modifizieren, um einen gepufferten Kanal zu verwenden und einen Blick auf die Ausgabe zu werfen. Beachten Sie, dass ich einen Aufruf von time.Sleep() am unteren Rand unserermain() -Funktion hinzugefügt habe, um unsere main() -Funktion träge genug zu blockieren, damit unsere Goroutinen die Ausführung abschließen können.

Haupt.go

Wenn wir dies ausführen, sollten wir nun sehen, dass unsere zweite Goroutine ihre Ausführung tatsächlich fortsetzt, unabhängig davon, dass in unserer main() Funktion kein zweiter Empfang aufgerufen wurde. Dank der time.Sleep(), wir können clearlyse die unterschied zwischen ungepufferte kanäle und ihre sperrung natur und ourbuffered kanäle und ihre nicht-blocking (wenn nicht voll) natur.

Go Channel TutorialCalculated Random Value: {} 1Calculated Random Value: {} 77This executes regardless as the send is now non-blockingThis executes regardless as the send is now non-blocking

Fazit

Also, in diesem ziemlich langen Tutorial haben wir es geschafft, etwas über die verschiedenen Arten von Kanälen in Go zu lernen. Wir haben die Unterschiede zwischen gepufferten und ungepufferten Kanälen entdeckt und wie wir sie in unseren gleichzeitigen go-Programmen zu unserem Vorteil nutzen können.

Wenn Ihnen dieses Tutorial gefallen hat, können Sie es mich gerne im Kommentarbereich unten wissen lassen. Wenn Sie Vorschläge haben, was ich besser machen könnte, würde ich sie gerne im Kommentarbereich unten hören!

Weiterführende Literatur

Wenn Ihnen dieser Artikel gefallen hat und Sie mehr über die Arbeit mit Concurrencyin Go erfahren möchten, empfehle ich Ihnen, unsere anderen Artikel zur Parallelität zu lesen:

  • Gehen Mutex Tutorial
  • Gehen Goroutinen Tutorial
  • Gehen sync.WaitGroup Tutorial

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.

Previous post Brunswick County Library System
Next post Sollten Sie Schränke malen oder färben? Pros & Cons von jedem