Quando um canal é buffer, isso significa que não bloqueará até que o buffer esteja cheio. Quando o buffer estiver cheio, o Goroutine de envio será bloqueado, pois tenta adicionar coisas ao canal.
Isso significa que isso vai bloquear:
c := make(chan int)
c <- 1 // Block here, this is unbuffered !
println(<-c)
E isso vai também quadra:
c := make(chan int, 2)
c <- 1
c <- 2
c <- 3 // Block here, buffer is full !
println(<-c)
Mas o ponto de Goroutines e Channel é precisamente executar as coisas simultaneamente, então isso 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
E da mesma forma:
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
No seu exemplo, você gera quatro goroutinas diferentes, que escrevem quatro números no mesmo canal em buffer. Como o buffer é 2 <16, eles acabarão bloqueando
Mas o cerne da questão é que a política Go é para Espere apenas a goroutina principal:
A execução do programa começa inicializando o pacote principal e a invocando a função principal. Quando a função principal retorna, o programa sai. Não espera que outras goroutinas (não principais) sejam concluídas.
Isso significa que em seu primeiro exemplo, o a Principal Goroutine estava bloqueando quando atingiu a linha c <- 3
. Como nenhum outro goroutine foi capaz de fazer qualquer coisa que pudesse desbloqueá -lo, o tempo de execução detectou que o programa foi impulsionado e relatou um erro.
No seu segundo exemplo, no entanto, gerado O bloqueio de Goroutines, enquanto o principal continua silenciosamente até chegar ao final de sua execução, momento em que todas as goroutinas (bloqueadas) geradas são mortas silenciosamente e nenhum erro é relatado.