formacioninformatica.es.

formacioninformatica.es.

Programación concurrente en Go

Introducción

La programación concurrente es una técnica esencial para aprovechar al máximo la potencia de los procesadores modernos y crear aplicaciones eficientes y escalables. Go es un lenguaje de programación diseñado específicamente para la programación concurrente. En este artículo, vamos a conocer los conceptos fundamentales de la programación concurrente en Go y cómo aplicarlos en nuestros proyectos.

Goroutines

Las goroutines son uno de los pilares fundamentales de la programación concurrente en Go. Una goroutine es una función ligera que se ejecuta de manera asincrónica, es decir, en segundo plano. Las goroutines son muy ligeras y se pueden ejecutar miles de ellas al mismo tiempo sin afectar el rendimiento de la aplicación. Para crear una goroutine en Go, simplemente agregamos la palabra clave "go" delante de la llamada a la función:

go miFuncion()

La función miFuncion se ejecutará de manera asincrónica en segundo plano mientras que el programa principal continúa ejecutándose.

Canales

Los canales son otro elemento clave en la programación concurrente de Go. Los canales permiten la comunicación entre goroutines y son fundamentales para garantizar la sincronización y la coordinación entre ellas. Los canales se pueden definir de la siguiente manera:

// Definición de un canal de enteros con capacidad 10 miCanal := make(chan int, 10)

Podemos enviar un valor a un canal utilizando la siguiente sintaxis:

miCanal <- 5

Y podemos recibir un valor de un canal utilizando la siguiente sintaxis:

x := <-miCanal

La operación de envío y de recepción son operaciones bloqueantes, es decir, el programa se detiene hasta que se complete la operación.

Seleccionador de canales

El seleccionador de canales es otra característica interesante de Go que permite la selección de un canal de comunicación entre varios canales al mismo tiempo. El selector de canales bloqueará la ejecución hasta que alguno de los canales esté listo para recibir o enviar datos. La sintaxis del seleccionador de canales es la siguiente:

select { case x := <- canal1: fmt.Println("Recibido", x) case canal2 <- 5: fmt.Println("Enviado 5 al canal2") }

En este ejemplo, el selector de canales esperará a que uno de los canales esté listo para recibir o enviar datos. Si el canal1 está listo para recibir un valor, se imprimirá "Recibido" junto con el valor recibido. Si el canal2 está listo para enviar un valor, se imprimirá "Enviado" junto con el valor enviado.

Primitivas de sincronización

Además de las goroutines y los canales, Go también proporciona una serie de primitivas de sincronización para garantizar la sincronización y la coordinación entre las goroutines. Uno de estos mecanismos es el grupo de espera (WaitGroup), que permite que una goroutine espere a que varias goroutines se completen. La definición de un grupo de espera es la siguiente:

var wg sync.WaitGroup

Para agregar goroutines al grupo de espera, usamos el método Add:

wg.Add(1)

Para indicar que una goroutine ha terminado, usamos el método Done:

wg.Done()

Y para esperar a que todas las goroutines agregadas al grupo terminen, utilizamos el método Wait:

wg.Wait()

Conclusión

La programación concurrente en Go es una técnica indispensable para aprovechar al máximo la potencia de los procesadores modernos y crear aplicaciones eficientes y escalables. En este artículo hemos visto los conceptos fundamentales de la programación concurrente en Go, incluyendo las goroutines, los canales, el seleccionador de canales y las primitivas de sincronización. Go es un lenguaje de programación cada vez más popular y su enfoque en la programación concurrente lo convierte en una herramienta poderosa para desarrollar aplicaciones de alto rendimiento y escalables. Si aún no has explorado la programación concurrente en Go, te recomendamos que comiences a hacerlo cuanto antes.