Aprenda cómo las rutinas y los canales permiten una concurrencia eficiente en sus programas Go.
La concurrencia es un aspecto crucial del desarrollo de software moderno, ya que permite que los programas manejen de manera eficiente múltiples tareas simultáneamente. Puede escribir programas que ejecuten varias operaciones que mejoren el rendimiento, la capacidad de respuesta y la utilización de recursos.
La concurrencia es una de las características responsables de la rápida adopción de Go. El soporte incorporado de Go para la programación concurrente se considera sencillo y ayuda a evitar errores comunes como condiciones de carrera y puntos muertos.
Concurrencia en Go
Go proporciona un soporte sólido para la concurrencia a través de varios mecanismos, todos disponibles en su biblioteca y cadena de herramientas estándar. ir programas lograr la concurrencia a través de goroutines y canales.
Las Goroutines son funciones ligeras que se ejecutan de forma independiente y se ejecutan simultáneamente con otras Goroutines dentro del mismo espacio de direcciones. Goroutines permite que múltiples tareas progresen simultáneamente sin una gestión de subprocesos explícita. Las Goroutines son más ligeras que los subprocesos del sistema operativo y Go puede ejecutar eficientemente miles o incluso millones de Goroutines simultáneamente.
Los canales son el mecanismo de comunicación para la coordinación y el intercambio de datos entre rutinas. Un canal es un conducto tipado que permite a las rutinas enviar y recibir valores. Los canales brindan sincronización para garantizar el intercambio seguro de datos entre goroutines al tiempo que evitan condiciones de carrera y otros problemas comunes de simultaneidad.
Al combinar rutinas y canales, Go proporciona un modelo de concurrencia potente y directo que simplifica el desarrollo de programas concurrentes al mismo tiempo que mantiene la seguridad y la eficiencia. Estos mecanismos le permiten utilizar fácilmente procesadores multinúcleo y crear aplicaciones altamente escalables y receptivas.
Cómo usar Goroutines para la ejecución simultánea de código
El tiempo de ejecución de Go administra goroutines. Goroutines tiene su pila, lo que les permite tener una huella ligera con un tamaño de pila inicial de unos pocos kilobytes.
Las rutinas Gor se multiplexan en varios subprocesos del sistema operativo mediante el tiempo de ejecución de Go. El programador de tiempo de ejecución de Go los programa en subprocesos disponibles mediante la distribución eficiente de la carga de trabajo, lo que permite la ejecución simultánea de varias gorutinas en menos subprocesos del sistema operativo.
Crear goroutines es sencillo. Usarás el ir palabra clave seguida de una llamada de función para declarar goroutines.
funciónprincipal() {
ir funcion1() // Crear y ejecutar gorutina para función1
ir funcion2() // Crear y ejecutar goroutine para function2// ...
}funciónfuncion1() {
// Código para función1
}
funciónfuncion2() {
// Código para función2
}
Cuando el programa invoca funcion1() y funcion2() con el ir palabra clave, el tiempo de ejecución de Go ejecuta las funciones simultáneamente como rutinas.
Aquí hay un ejemplo de uso de una gorutina que imprime texto en la consola:
paquete principal
importar (
"fmt"
"tiempo"
)funciónimprimirTexto() {
para yo := 1; yo <= 5; yo++ {
fmt. imprimir("Imprimir texto", i)
tiempo. Dormir(1 * tiempo. Segundo)
}
}funciónprincipal() {
ir imprimirTexto() // Iniciar una gorutina para ejecutar la función imprimirTexto al mismo tiempo// Realizar otras tareas en la rutina principal
para yo := 1; yo <= 5; yo++ {
fmt. imprimir("Realización de otras tareas", i)
tiempo. Dormir(500 * tiempo. Milisegundo)
}
// Espera a que termine la gorutina
tiempo. Dormir(6 * tiempo. Segundo)
}
El imprimirTexto La función imprime repetidamente algún texto en la consola con un para bucle que se ejecuta cinco veces después de un retraso de un segundo entre cada declaración con el paquete de tiempo.
El principal la función inicia una gorutina llamando ir a imprimirTexto, que pone en marcha el imprimirTexto función como una gorutina concurrente separada que permite que la función se ejecute simultáneamente con el resto del código en el principal función.
Finalmente, para asegurarse de que el programa no se cierra antes de que imprimirTexto gooutine termina, el tiempo. Dormir La función pausa la rutina principal durante seis segundos. En escenarios del mundo real, usaría mecanismos de sincronización como canales o grupos de espera para coordinar la ejecución de goroutines.
Uso de canales de comunicación y sincronización
Goroutines tiene soporte integrado para la comunicación y la sincronización a través de canales, lo que hace que la escritura sea simultánea código más fácil que los hilos tradicionales, que a menudo requieren mecanismos de sincronización manual como bloqueos y semáforos.
Puede pensar en los canales como conductos para el flujo de datos entre rutinas. Una gorutina puede enviar un valor al canal y otra gorutina puede recibir ese valor del canal. Este mecanismo garantiza que el intercambio de datos sea seguro y sincronizado.
Usarás el operador para enviar y recibir datos a través de canales.
Aquí hay un ejemplo que demuestra el uso básico de los canales para la comunicación entre dos rutinas:
funciónprincipal() {
// Crear un canal sin búfer de tipo cadena
ch := hacer(chancadena)// Goroutine 1: Envía un mensaje al canal
irfunción() {
ch "¡Hola, Canal!"
}()
// Goroutine 2: Recibe el mensaje del canal
mensaje := fmt. Imprimir (mensaje) // Salida: ¡Hola, canal!
}
El canal en el principal función es un canal sin búfer llamado ch creado con el hacer() función. La primera rutina envía el mensaje "¡Hola, canal!" en el canal usando el operador, y la segunda rutina recibe el mensaje del canal usando el mismo operador. Finalmente, el principal La función imprime el mensaje recibido en la consola.
Puede definir canales escritos. Especificará el tipo de canal en la creación. Aquí hay un ejemplo que demuestra el uso de diferentes tipos de canales:
funciónprincipal() {
// Canal sin búfer
canal1 := hacer(chanEn t)// Canal amortiguado con una capacidad de 3
ch2 := hacer(chancadena, 3)// Enviando y recibiendo valores de los canales
canal1 42// Enviar un valor a ch1
valor1 := // Recibir un valor de ch1
ch2 "Hola"// Enviar un valor a ch2
valor2 := // Recibir un valor de ch2
}
El principal La función crea dos canales: ch1 es un canal entero sin búfer, mientras que ch2 es un canal de cadena con búfer con una capacidad de 3. Puede enviar y recibir valores hacia y desde estos canales usando el operador (los valores tienen que ser del tipo especificado).
Puede usar los canales como mecanismos de sincronización para coordinar la ejecución de rutinas aprovechando la naturaleza de bloqueo de las operaciones del canal.
funciónprincipal() {
ch := hacer(chanbool)irfunción() {
fmt. imprimir("Gorutina 1")
ch verdadero// finalización de la señal
}()irfunción() {
// Espere la señal de finalización de Goroutine 1
fmt. imprimir("Gorutina 2")
}()
// Espere la señal de finalización de Goroutine 2
fmt. imprimir("Rutina principal")
}
El ch el canal es booleano. Dos goroutines se ejecutan simultáneamente en el principal función. Goroutine 1 señala su finalización mediante el envío de un verdadero valor en el canal ch. Goroutine 2 espera la señal de finalización al recibir un valor del canal. Finalmente, la rutina principal espera la señal de finalización de la rutina dos.
Puede crear aplicaciones web en Go With Gin
Puede crear aplicaciones web de alto rendimiento en Go con Gin mientras aprovecha las funciones de simultaneidad de Go.
Puede usar Gin para manejar el enrutamiento HTTP y el middleware de manera eficiente. Aproveche el soporte de simultaneidad incorporado de Go mediante el empleo de rutinas y canales para tareas como consultas de bases de datos, llamadas a API u otras operaciones de bloqueo.