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?


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

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 .


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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.