En Go, un canal es un medio para transmitir datos entre gorutinas con sincronización. Se distinguen:
Usar canales sin búfer es conveniente donde la sincronización es crítica y se necesita garantizar que el emisor y el receptor se encuentren en el mismo lugar del código. Los búferes son adecuados para la transmisión de datos “con margen” — para organizar colas, trabajadores, tareas asíncronas.
func main() { ch := make(chan int) // sin búfer go func() { ch <- 42 // se bloquea hasta que haya un receptor }() fmt.Println(<-ch) bufch := make(chan int, 2) // con búfer de 2 elementos bufch <- 1 // no se bloquea bufch <- 2 // no se bloquea // el siguiente envío se bloqueará si no hay lectura }
¿Puede un canal con búfer servir como sustituto de una cola entre decenas de productores y consumidores sin sincronización adicional?
A menudo se responde — “sí”. En realidad, solo si no es importante garantizar el orden y los mensajes no se pierden. Con varios lectores/escritores pueden ocurrir condiciones de carrera y pérdida de datos, por lo que el control de sincronización sigue siendo necesario (piscina de trabajadores, mutex, contextos para cerrar canales).
Historia
En el procesamiento de registros, los programadores utilizaron un canal con búfer de longitud 1000 para transmitir eventos entre el analizador y el agregador. Al detener el servicio, olvidaron cerrar el canal, y parte de los eventos "se perdió" — los trabajadores terminaron antes de procesar todo el búfer. Se corrigió cerrando los canales explícitamente y bloqueando hasta la descarga completa.
Historia
Al intentar reemplazar una cola con mutex por un canal con búfer en un servicio distribuido, no se consideraron situaciones de "emisores colgados": con un búfer completo, la bloqueación de envío finalmente ralentizó todo el sistema, provocó tiempos de espera y la interfaz comenzó a "ralentizarse". Después de un análisis, se devolvió parte de la sincronización a través de variables de condición.
Historia
En el módulo de telemetría se utilizó un canal sin búfer para el registro de errores entre el módulo y el consumidor. Debido a una demora aleatoria en el procesamiento, el escritor se bloqueó, y en un minuto se acumuló una cola de cientos de miles de datos en gorutinas — surgió "out of goroutines". Se corrigió reemplazando el canal sin búfer por un canal con búfer y un trabajador asíncrono para limpiar la cola.