Was ist die Kanalpuffergröße?

82

Ich versuche, einen asynchronen Kanal zu erstellen, und habe mir http://golang.org/ref/spec#Making_slices_maps_and_channels angesehen .

c := make(chan int, 10)         // channel with a buffer size of 10

Was bedeutet es, dass die Puffergröße 10 beträgt? Was genau repräsentiert / begrenzt die Puffergröße?

Tech163
quelle
Siehe hier und weiter
Ivan Black
Siehe hier auch hilfreich. Sehr direkt und leicht zu verstehen :)
Ardi Nusawan

Antworten:

157

Die Puffergröße ist die Anzahl der Elemente, die ohne Sendeblockierung an den Kanal gesendet werden können. Standardmäßig hat ein Kanal eine Puffergröße von 0 (Sie erhalten dies mit make(chan int)). Dies bedeutet, dass jeder einzelne Sendevorgang blockiert wird, bis eine andere Goroutine vom Kanal empfängt. Ein Kanal der Puffergröße 1 kann 1 Element enthalten, bis Blöcke gesendet werden

c := make(chan int, 1)
c <- 1 // doesn't block
c <- 2 // blocks until another goroutine receives from the channel
Lily Ballard
quelle
21
Gute Antwort. Effective Go hat ein schönes Kapitel mit dem Titel "Concurrency", das auf Kanälen erklärt wird. Sehr zu empfehlen: golang.org/doc/effective_go.html
Levi
Ich spiele damit herum und mache (chan int, 1), dass 3 Werte vor dem Blockieren in meinen Kanal übergeben werden (Testen mit log.Printlns), und die Standardeinstellung ist, 2 vor dem Blockieren einzulassen. Irgendeine Idee warum:
Mauricio
@ Mauricio Das klingt ziemlich komisch. Ich habe gerade Go 1.8.3 lokal getestet und auch die "Try Go" -Funktionalität bei golang.org verwendet . In beiden Fällen verhält es sich immer noch so, wie es in meiner Antwort dokumentiert ist.
Lily Ballard
1
Ich freue mich über die Antwort, habe aber den Datendruck auf meiner Konsole falsch interpretiert. Es funktioniert wie beschrieben.
Mauricio
10

Der folgende Code veranschaulicht das Blockieren des ungepufferten Kanals:

// to see the diff, change 0 to 1
c := make(chan struct{}, 0)
go func() {
    time.Sleep(2 * time.Second)
    <-c
}()
start := time.Now()
c <- struct{}{} // block, if channel size is 0
elapsed := time.Since(start)
fmt.Printf("Elapsed: %v\n", elapsed)

Sie können mit dem Code spielen hier .

Vladimir Bauer
quelle
0
package main

import (
    "fmt"
    "time"
)

func receiver(ch <-chan int) {
    time.Sleep(500 * time.Millisecond)
    msg := <-ch
    fmt.Printf("receive messages  %d from the channel\n", msg)
}

func main() {
    start := time.Now()
    zero_buffer_ch := make(chan int, 0)
    go receiver(zero_buffer_ch)
    zero_buffer_ch <- 444
    elapsed := time.Since(start)    
    fmt.Printf("Elapsed using zero_buffer channel: %v\n", elapsed)

    restart := time.Now()
    non_zero_buffer_ch := make(chan int, 1)
    go receiver(non_zero_buffer_ch)
    non_zero_buffer_ch <- 4444
    reelapsed := time.Since(restart)
    fmt.Printf("Elapsed using non zero_buffer channel: %v\n", reelapsed)
}

Ergebnis:

Empfangen von Nachrichten 444 vom Kanal

Abgelaufen mit dem Kanal zero_buffer: 505.6729ms

Verstrichen mit einem Nicht-Null-Puffer-Kanal: 0s

user2480972
quelle