Cuando se amortigua un canal, esto significa que no bloqueará hasta que el búfer esté lleno. Una vez que el búfer está lleno, el envío de Goroutine bloqueará a medida que intente agregar cosas al canal.
Esto significa que esto bloqueará:
c := make(chan int)
c <- 1 // Block here, this is unbuffered !
println(<-c)
Y esto lo hará además bloquear:
c := make(chan int, 2)
c <- 1
c <- 2
c <- 3 // Block here, buffer is full !
println(<-c)
Pero el punto de las goroutinas y el canal es precisamente ejecutar las cosas simultáneamente, por lo que esto funcionará:
c := make(chan int)
go func() { c <- 1; }() // This will block in the spawned goroutine until...
println(<-c) // ... this line is reached in the main goroutine
Y de manera similar:
c := make(chan int, 2)
go func() { // `go ...` spawns a goroutine
c <- 1 // Buffer is not full, no block
c <- 2 // Buffer is not full, no block
c <- 3 // Buffer is full, spawned goroutine is blocking until...
}()
println(<-c) // ... this line is reached in the main goroutine
En su ejemplo, genera cuatro goroutinas diferentes, que escriben cuatro números en el mismo canal amortiguado. Como el búfer es 2 <16, terminarán bloqueando
Pero el quid del asunto es que la política de Go es Espera solo a la goroutina principal:
La ejecución del programa comienza inicializando el paquete principal y luego invocando la función principal. Cuando la función principal regresa, el programa sale. No espera a que se completen otras goroutinas (no principales).
Esto significa que en su primer ejemplo, el principal Goroutine estaba bloqueando cuando llegó a la línea c <- 3
. Como ninguna otra Goroutine pudo hacer algo que pudiera desbloquearlo, el tiempo de ejecución detectó que el programa estaba en punto y informó un error.
En su segundo ejemplo, sin embargo, generado Bloque de goroutinas, mientras que el principal continúa en silencio hasta que alcanza el final de su ejecución, momento en el cual todas las goroutinas generadas (bloqueadas) son asesinadas en silencio, y no se informa ningún error.