English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Golang Grund教程

Golang Kontrollanweisungen

Golang Funktion & Methode

Golang Struktur

Golang Schnittstelle & Array

Golang Zeichenkette (String)

Golang Zeiger

Golang Schnittstelle

Golang Konkurrenz

Golang Ausnahme (Error)

Golang andere Sachen

Go-Kommunikationskanal(Channel)

In der Programmiersprache Go sind Kanäle das Medium zur Kommunikation zwischen Goroutines und ermöglichen eine lockfreie Kommunikation. Mit anderen Worten, ein Kanal ist eine Technik, die es einer Goroutine ermöglicht, Daten an eine andere Goroutine zu senden. Standardmäßig sind Kanäle bidirektional, was bedeutet, dass Goroutines Daten über denselben Kanal senden oder empfangen können, wie im folgenden Diagramm gezeigt:

Erstellen eines Kanals

In der Programmiersprache Go wird ein Kanal mit dem chan-Schlüsselwort erstellt und dieser Kanal kann nur Daten desselben Typs übertragen, es ist nicht erlaubt, von demselben Kanal Daten verschiedener Typen zu übertragen.

Syntax:

var Channel_name chan Type

Sie können auch eine Kurzdeklaration verwenden, um über die make()-Funktion einen Kanal zu erstellen.

Syntax:

channel_name:= make(chan Type)
package main
import "fmt"
func main() {
    //Ein Kanal wird mit dem var-Schlüsselwort erstellt
    var mychannel chan int
    fmt.Println("Kanalue: ", mychannel)
    fmt.Printf("Kanalart: %T ", mychannel)
    // Die Funktion make() verwendet, um einen Kanal zu erstellen
    mychannel1 := make(chan int)
    fmt.Println("\nKanal1Wert: ", mychannel1)
    fmt.Printf("Kanal1Art: %T "1)
}

Ausgabe:

Kanalue: <nil>
Kanalart: chan int
Kanal1Wert: 0xc0000160c0
Kanal1Art: chan int

Daten senden und empfangen von Kanälen

In der Programmiersprache Go arbeiten Kanäle mit zwei Hauptoperationen: Senden und Empfangen, die beide als Kommunikation zusammengefasst werden.<-Die Richtung des Operators zeigt an, ob Daten empfangen oder gesendet werden. In Kanälen blockieren Senden und Empfang standardmäßig, bis am anderen Ende keine Daten mehr vorhanden sind. Dies ermöglicht es Goroutines, ohne explizite Locks oder Conditionsynchrone miteinander zu synchronisieren.

  1. Sendevorgänge:Sendevorgänge werden verwendet, um Daten von einem Goroutine über einen Kanal an eine andere Goroutine zu senden. Wie int, float64Werte wie bool können sicher und einfach über Kanäle gesendet werden, da sie kopiert werden, daher besteht keine Gefahr eines unerwarteten parallelen Zugriffs auf denselben Wert. Ebenso sind Strings sicher, da sie unveränderlich sind. Es ist jedoch nicht sicher, Zeiger oder Referenzen (z.B. Slices, Map-Sammlungen) über Kanäle zu senden, da der Wert des Zeigers oder der Referenz durch gleichzeitig sendende oder empfangende Goroutines geändert werden kann, und das Ergebnis ist nicht vorhersehbar. Daher muss sichergestellt werden, dass Zeiger oder Referenzen im Kanal nur von einer Goroutine gleichzeitig aufgerufen werden.

    Mychannel <- element

    Die obige Anweisung zeigt, dass die Daten (element)<-unter Verwendung des Operators an den Kanal (Mychannel) gesendet wird.

  2. Empfangsoperation:Der Empfangsoperation wird verwendet, um die von dem sendenden Element gesendeten Daten zu empfangen.

    element := <-Mychannel

    Die obige Anweisung zeigt, dass das Element Daten vom Kanal (Mychannel) empfängt. Wenn das Ergebnis der empfangenen Anweisung nicht verfügbar ist (nicht erforderlich), ist dies ebenfalls eine gültige Anweisung. Sie können auch wie folgt eine receive-Anweisung schreiben:

    <-Mychannel
package main 
  
import "fmt"
  
func myfunc(ch chan int) { 
  
    fmt.Println(234 + <-ch) 
} 
func main() { 
    fmt.Println("Hauptmethode beginnt") 
    //Erstellen eines Kanals l 
    ch := make(chan int) 
  
    go myfunc(ch) 
    ch <- 23 
    fmt.Println("Hauptmethode beendet") 
}

Ausgabe:

Hauptmethode beginnt
257
Hauptmethode beendet

Kanal schließen

Sie können auch den close()-Funktion verwenden, um den Kanal zu schließen. Dies ist eine eingebettete Funktion, die einen Beleg setzt, der angibt, dass keine Werte mehr in den Kanal gesendet werden.

Syntax:

close()

Sie können auch den for-Schleifenbereich verwenden, um den Kanal zu schließen. Hierbei kann der Empfänger-Goroutine mithilfe der gegebenen Syntax überprüfen, ob der Kanal geöffnet oder geschlossen ist:

ele, ok := <- Mychannel

Hierbei bedeutet ein Wert von ok auf true, dass der Kanal geöffnet ist und daher Leseoperationen ausgeführt werden können. Und wenn der Wert auf false gesetzt ist, bedeutet dies, dass der Kanal geschlossen ist und daher keine Leseoperationen ausgeführt werden.

//Die Go-Programmierung zeigt, wie
//Schließen des verwendeten Kanals
//range-Schleife und Schließfunktion
package main
import "fmt"
func myfun(mychnl chan string) {
    for v := 0; v < 4; v++ {
        mychnl <- "w3codebox
    }
    close(mychnl)
}
func main() {
    //Erstellen eines Kanals
    c := make(chan string)
    // Verwendung von Goroutine
    go myfun(c)
    //Wenn der Wert von ok auf true gesetzt ist, bedeutet dies, dass der Kanal geöffnet ist und Daten gesendet oder empfangen werden können
    //Wenn der Wert von ok auf false gesetzt ist, bedeutet dies, dass der Kanal geschlossen ist
    for {
        res, ok := <-c
        if ok == false {
            fmt.Println("Kanal schließen ", ok)
            break
        }
        fmt.Println("Kanal öffnen ", res, ok)
    }
}

Ausgabe:

Kanal öffnen w3codebox true
Kanal öffnen w3codebox true
Kanal öffnen w3codebox true
Kanal öffnen w3codebox true
Kanal schließen false

Wichtige Hinweise

  • Verhinderung des Sendens und Empfangens:Wenn Daten in den Kanal gesendet werden, wird der Kontrollfluss im sendenden Statement blockiert, bis ein anderes goroutine das Daten aus dem Kanal liest. Ähnlich wird das read-Statement blockiert, bis ein anderes goroutine eine Anweisung ausführt.

  • Nullwert-Kanal: Kanalhat den Wert nil.

  • For-Loop im Kanal: Der for-Loop kann die in den Kanal gesendeten Werte in der Reihenfolge durchlaufen, bis er geschlossen wird.

    Syntax:

    for item := range Chnl { 
         // Anweisung..
    }
    package main 
    import "fmt"
      
    func main() { 
      
        // Die Funktion make() verwendet, um einen Kanal zu erstellen
        mychnl := make(chan string) 
      
        // Anonyme goroutine 
        go func() { 
            mychnl <- "GFG"
            mychnl <- "gfg"
            mychnl <- "Geeks"
            mychnl <- "w3codebox
            close(mychnl) 
        } 
      
        //Mit dem for-Loop
        for res := range mychnl { 
            fmt.Println(res) 
        } 
    }

    Ausgabe:

    GFG
    gfg
    Geeks
    w3codebox
  • Länge des Kanals:In Kanälen können SieFunktion len()Die Länge des Kanals finden. Hier stellt die Länge die Anzahl der in den Puffer der Kanalbücher eingereihten Werte dar.

    package main 
      
    import "fmt"
    func main() { 
      
        // Die Funktion make() verwendet, um einen Kanal zu erstellen 
        mychnl := make(chan string, 4) 
        mychnl <- "GFG"
        mychnl <- "gfg"
        mychnl <- "Geeks"
        mychnl <- "w3codebox
        // Die Funktion len() verwendet, um die Länge des Kanals zu ermitteln 
        fmt.Println("Länge des Kanals: ", len(mychnl)) 
    }

    Ausgabe:

    Länge des Kanals:  4
  • Kapazität des Kanals:In Kanälen können Sie mit der Funktion cap() die Kapazität des Kanals finden. Hier stellt die Kapazität die Größe des Puffers dar.

    package main
    import "fmt"
    func main() {
        // Die Funktion make() verwendet, um einen Kanal zu erstellen
        mychnl := make(chan string, 4)
        mychnl <- "GFG"
        mychnl <- "gfg"
        mychnl <- "Geeks"
        mychnl <- "w3codebox
        // Die Funktion cap() verwendet, um die Kapazität des Kanals zu ermitteln
        fmt.Println("Kapazität des Kanals: ", cap(mychnl))
    }

    Ausgabe:

    Kapazität des Kanals:  5
  • Select und case-Statement im Kanal:In der Programmiersprache Go ähnelt das select-Statement einem switch-Statement ohne Eingabeparameter. Mit dem select-Statement können Sie in Kanälen eine einzelne Operation aus mehreren durch case-Blöcke bereitgestellten Operationen ausführen.