Lecciones del módulo (2/5)
Canales: comunicación tipada
Los canales son el mecanismo idiomático de comunicación entre gorutinas. La filosofía Go (Rob Pike):
"No comuniques compartiendo memoria; comparte memoria comunicando."
Un canal es una cola FIFO escrita, de tipo seguro y segura para concurrencia.
uso. Combinado con go, es el componente principal de Go.
concurrencia.
Crear, enviar, recibir
ch := make(chan int) // canale di int, unbuffered
go func() {
ch <- 42 // invia (può bloccare)
}()
v := <-ch // ricevi (può bloccare)
fmt.Println(v) // 42Sintaxis:
make(chan T)omake(chan T, N)para buffer.ch <- venvía.v := <-chrecibe.v, ok := <-chrecibe con una bandera (ok = falsesi el canal está cerrado Y vacío).
Sin búfer: encuentro
Un canal sin búfer (capacidad 0) bloquea:
- el remitente hasta que un receptor esté listo;
- el receptor hasta que un remitente esté listo.
Es una cita sincrónica: útil como "señal" o para garantizar que el valor ha sido entregado.
Buffered: cola hasta N
ch := make(chan int, 3)
ch <- 1 // non blocca
ch <- 2 // non blocca
ch <- 3 // non blocca
ch <- 4 // BLOCCA: il buffer è pienoEl remitente bloquea sólo cuando el búfer está lleno; el receptor solamente cuando está vacío.
cerca y a distancia
El remitente cierra el canal cuando no hay más valores:
ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 3
close(ch)
for v := range ch { // termina quando ch è chiuso E vuoto
fmt.Println(v)
}for range sobre un canal se itera hasta que el canal se cierra (y se drena).
Es el patrón más limpio para “consumir todo lo que llega”.
Direccionalidad en firmas
Los parámetros de función pueden restringir la dirección:
func producer(out chan<- int) { // solo invio
out <- 1
close(out)
}
func consumer(in <-chan int) { // solo ricezione
for v := range in {
fmt.Println(v)
}
}chan<- T = solo envío, <-chan T = solo recepción. Un bidireccional
El canal chan T se puede pasar a cualquiera de los dos (conversión implícita). eso
mejora la claridad y previene errores.
Patrones comunes (vista previa)
- Grupo de trabajadores: N gorutinas consumen desde
jobs <-chan T, producen enresults chan<- R. - Pipeline: etapas conectadas por canales.
- Señal hecho: un canal
chan struct{}cerrado para señal de "parada".
done := make(chan struct{})
go func() {
<-done // blocca finché qualcuno chiude done
cleanup()
}()
close(done) // segnale di stopchan struct{} es el canal de "señal": cero bytes de carga útil, solo
sincronización.
Pruébalo
Cree un canal int sin búfer, envíe 42 desde una rutina, recíbalo en principal e imprímalo.
Mostrar pista
Sin un búfer, el remitente y el receptor se sincronizan.
Solución disponible después de 3 intentos
Envíe 1,2,3 a través de un canal almacenado en búfer, ciérrelo y luego imprima todo con for-range.
Mostrar pista
`for range` sobre un canal termina cuando el canal se cierra y se drena.
Solución disponible después de 3 intentos
¿Qué hace un canal SIN BUFFERED cuando el remitente envía pero ningún receptor está listo?
ch := make(chan int)
ch <- 1 // ?Resumen
- Canal = cola FIFO escrita, segura entre gorutinas.
- Sin búfer: encuentro (el remitente y el receptor se sincronizan).
- Buffered: desacoplamiento, se bloquea solo cuando está lleno/vacío.
close(ch): sólo el remitente;for rangeconsume hasta cerrar.- Direccionalidad:
chan<- T(solo envío),<-chan T(solo recepción). chan struct{}como canal de señal para sincronización pura.