Golang ist eine stark typisierte Sprache, die für ihre hohe Parallelität und prägnante Syntax bekannt ist. Unter diesen ist Chan eine der gängigen Kommunikationsmethoden in Golang und ein wichtiger Bestandteil der Implementierung gleichzeitiger Programmierung. In diesem Artikel werfen wir einen detaillierten Blick auf die Verwendung und die Grundlagen von Chan in Golang.
1. Das Konzept und die Funktion von Chan
chan ist ein wichtiger Weg, um die Kommunikation zwischen Goroutinen in Golang zu erreichen, die als Pipeline bezeichnet wird. Es handelt sich um eine threadsichere Datenstruktur, die zur Weitergabe von Informationen in Golang-Programmen verwendet wird. Chan kann unidirektionale und bidirektionale Kommunikation implementieren, zum Senden und Empfangen von Daten sowie zum Synchronisieren von Goroutinen verwendet werden.
2. Typen und Verwendung von Chan
Chan in Golang ist ein Typ, der mit der Make-Funktion erstellt werden kann. Die Syntax lautet wie folgt:
ch := make(chan int)
wobei int den Typ der in der Pipeline übergebenen Daten darstellt. Bei der Verwendung von Chan müssen Sie die folgenden Punkte beachten:
Sowohl der Sende- als auch der Empfangsvorgang blockieren. Das heißt, wenn keine Übereinstimmung zwischen Sende- und Empfangsvorgang besteht, wird die Goroutine immer blockiert zu diesem Vorgang. Zum Beispiel:
ch := make(chan int) // 发送操作 go func() { ch <- 1 }() // 接收操作 a := <- ch
In diesem Beispiel haben wir eine Pipe vom Typ int erstellt und jeweils Sende- und Empfangsvorgänge ausgeführt. Bei der Sendeoperation senden wir einen Wert 1 an die Pipe; bei der Empfangsoperation nehmen wir den Wert aus der Pipe und weisen ihn der Variablen a zu. Da sowohl Sende- als auch Empfangsvorgänge blockieren, wartet dieses Programm, bis die Sende- und Empfangsvorgänge übereinstimmen, bevor es normal beendet werden kann.
Mit der Schließfunktion können Sie die Pipe schließen. Die geschlossene Pipe kann nicht erneut gesendet werden. Zum Beispiel:
ch := make(chan int) // 发送操作 go func() { ch <- 1 close(ch) }() // 循环接收操作 for { if val, ok := <-ch; ok { fmt.Println(val) } else { break } }
In diesem Beispiel rufen wir die Schließfunktion nach dem Sendevorgang auf und verwenden dann eine for-Schleife, um die Pipeline zu empfangen. Im Empfangsvorgang wird ok verwendet, um zu bestimmen, ob die Pipeline geschlossen wurde, um einen Deadlock zu verhindern.
Einseitiger Kanal kann durch Festlegen der Rohrrichtung erstellt werden. Zum Beispiel:
ch := make(chan int) // 双向chan // 定义只能发送的单向chan sendCh := make(chan <- int) // 定义只能接收的单向chan recvCh := make(<- chan int) // 发送操作时可以使用单向chan go func() { sendCh <- 1 }() // 接收操作时也可以使用单向chan a := <-recvCh
In diesem Beispiel erstellen wir einen bidirektionalen Kanal über die Make-Funktion und erstellen dann einen unidirektionalen Kanal, der nur über die Make-Funktion senden und nur empfangen kann. Im Sendevorgang und im Empfangsvorgang verwenden wir sendCh bzw. recvCh.
select-Anweisung kann den Status mehrerer Pipelines gleichzeitig überwachen und für gleichzeitige Lese- und Schreibvorgänge von Pipelines verwendet werden. Zum Beispiel:
ch1 := make(chan int) ch2 := make(chan int) // 发送操作 go func() { ch1 <- 1 }() // 使用select语句并发监听多个管道 select { case a := <- ch1: fmt.Println(a) case b := <- ch2: fmt.Println(b) }
In diesem Beispiel haben wir zwei Pipelines ch1 und ch2 erstellt und den Wert 1 in einer Goroutine an ch1 gesendet. Danach haben wir die Select-Anweisung verwendet, um die beiden Pipes abzuhören, und die Case-Anweisung, die den ersten Wert empfangen hat, wurde zuerst ausgeführt.
3. Das Grundprinzip von Chan
In Golang wird Chan auf Basis einer speziellen Datenstruktur implementiert. Wenn wir die Make-Funktion verwenden, um einen Kanal zu erstellen, erstellen wir tatsächlich ein Slice mit einem Wert von Null und einer Länge von 0, das als Kanal bezeichnet wird.
Wir können das Prinzip von Chan wie folgt verstehen:
Beim Ausführen eines Sendevorgangs werden die zu sendenden Daten an das Slice am unteren Rand des Kanals angehängt. Wenn die Länge des Kanals 0 ist, ist der Index des hinzugefügten Elements 0. Wenn die Länge des Kanals nicht 0 ist, ist der Index des hinzugefügten Elements die Länge des Kanals.
Wenn die Länge des Kanals ihre obere Kapazitätsgrenze erreicht hat, wird ein größerer Slice im Speicher erstellt und die Elemente im ursprünglichen Slice werden in den neuen Slice kopiert. Daher werden beim Ausführen eines Sendevorgangs Speicherverwaltungs- und Kopiermechanismen verwendet.
Beim Ausführen des Empfangsvorgangs wird das erste angehängte Element aus dem Slice am unteren Rand des Kanals entfernt. Wenn im Slice keine Elemente vorhanden sind, wird gewartet, bis ein Element verfügbar ist. Wenn der Kanal geschlossen wurde, gibt die Empfangsoperation sofort einen Nullwert zurück.
Wenn beim Ausführen eines Sende- oder Empfangsvorgangs die Slice-Länge des Kanals ihre obere Kapazitätsgrenze erreicht hat oder bereits Daten im Kanal auf den Empfang warten, bleibt der Sende- oder Empfangsvorgang blockiert bis genügend Speicherplatz oder Daten verfügbar sind.
Beim Schließen eines Kanals wird der Status des Kanals auf geschlossen gesetzt und es können keine Daten mehr gesendet werden. Wenn im Kanal nicht empfangene Daten vorhanden sind, kann der Empfangsvorgang fortgesetzt werden, bis keine Daten mehr im Kanal vorhanden sind.
Zusammenfassung
Chan in Golang ist ein wichtiger Weg, um die Kommunikation zwischen Goroutinen zu erreichen, und es ist auch in Bezug auf die Syntax sehr prägnant. Für die gleichzeitige Programmierung ist es sehr wichtig, die grundlegende Verwendung und die Prinzipien von Chan zu beherrschen.
Das obige ist der detaillierte Inhalt vonVerwendung von Golang Chan. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!