¿Cuál es el tamaño del búfer de canal?

82

Estoy intentando crear un canal asincrónico y he estado mirando http://golang.org/ref/spec#Making_slices_maps_and_channels .

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

¿Qué significa que el tamaño del búfer es 10? ¿Qué representa / limita específicamente el tamaño del búfer?

Tech163
fuente
Vea aquí y más
Ivan Black
Véase aquí también útil. Muy directo y fácil de entender :)
Ardi Nusawan

Respuestas:

157

El tamaño del búfer es el número de elementos que se pueden enviar al canal sin el bloqueo de envío. De forma predeterminada, un canal tiene un tamaño de búfer de 0 (lo obtiene con make(chan int)). Esto significa que cada envío se bloqueará hasta que reciba otra goroutine del canal. Un canal de tamaño de búfer 1 puede contener 1 elemento hasta enviar bloques, por lo que obtendría

c := make(chan int, 1)
c <- 1 // doesn't block
c <- 2 // blocks until another goroutine receives from the channel
Lily Ballard
fuente
21
Buena respuesta. Effective Go tiene un buen capítulo titulado "Concurrencia" que explica los canales. Muy recomendable: golang.org/doc/effective_go.html
Levi
Estoy jugando con esto y make (chan int, 1) permite que se pasen 3 valores a mi canal antes del bloqueo (probándolo con log.Printlns), y el valor predeterminado es dejar entrar 2 antes del bloqueo. Alguna idea de por qué:
Mauricio
@Mauricio Eso suena bastante raro. Acabo de probar usando Go 1.8.3 localmente, y también usando la funcionalidad "Try Go" en golang.org , y en ambos casos todavía se comporta como se documenta en mi respuesta.
Lily Ballard
1
Agradezco la respuesta, pero en realidad estaba malinterpretando la impresión de datos en mi consola. Funciona como lo describiste.
Mauricio
10

El siguiente código ilustra el bloqueo de un canal sin búfer:

// 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)

Puedes jugar con el código aquí .

Vladimir Bauer
fuente
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)
}

resultado:

recibir mensajes 444 del canal

Transcurrido usando el canal zero_buffer: 505.6729ms

Transcurrido usando un canal distinto de zero_buffer: 0s

usuario2480972
fuente