¿Qué son y cómo usar correctamente las Go Routines y canales en Go?
En el mundo de la programación concurrente, las Go Routines y los canales de comunicación son elementos esenciales que pueden mejorar significativamente el rendimiento de tus proyectos en Go. Entender su funcionamiento te permitirá crear aplicaciones más eficientes y robustas. A continuación, te explicamos sus fundamentos, cómo implementarlos en tu código, y terminamos con los conceptos de apuntadores para ofrecerte un panorama más amplio de su uso práctico.
¿Cómo funcionan las Go Routines y su implementación?
Las Go Routines son la herramienta fundamental en Go para llevar a cabo tareas de manera concurrente. Piensa en ellas como funciones que corren de manera asíncrona en el mismo hilo o en hilos diferentes, permitiéndote realizar múltiples tareas a la vez sin bloquear el flujo del programa principal.
Para lanzar una Go Routine, simplemente utilizas la palabra reservada go
antes de llamar a la función deseada:
func DoSomething() {
time.Sleep(3 * time.Second)
fmt.Println("done")
}
func main() {
go DoSomething()
fmt.Println("This will print before 'done' due to asynchrony")
}
Como nota, una Go Routine por sí sola no es monitoreada, lo que significa que el mensaje "done" podría no imprimirse si main
termina antes de que DoSomething se complete. Aquí es donde entran los canales.
¿Qué rol juegan los canales en la comunicación entre Go Routines?
Los canales en Go permiten que múltiples Go Routines se comuniquen entre sí. Un canal es esencialmente una tubería a través de la cual puedes enviar y recibir valores entre diferentes partes de tu programa.
Para interactuar mediante un canal, primero debes crearlo y luego modificar tu función para que acepte el canal como parámetro:
func DoSomething(c chan int) {
time.Sleep(3 * time.Second)
fmt.Println("done")
c <- 1
}
func main() {
c := make(chan int)
go DoSomething(c)
<-c
}
En este ejemplo, main
se bloqueará hasta que DoSomething
envíe un valor al canal, asegurando que la función 'done' se imprima antes de que el programa finalice por completo.
¿Cuál es la importancia de los apuntadores en Go?
Los apuntadores en Go son perfectamente necesarios cuando necesitas manejar un valor por su referencia, en lugar de por su copia. Esto es útil para optimizar el uso de memoria y lograr que las funciones modifiquen el estado de una variable fuera de su ámbito local.
Imagina que tienes la variable g
y quieres manejar su dirección de memoria:
var g = 25
fmt.Println(g)
var h *int = &g
fmt.Println(h)
Ahora, para acceder al valor real donde apunta h
, utilizamos el operador asterisco (*
):
fmt.Println(*h)
Es esencial distinguir entre el uso del operador dirección (&
) para referirse a la dirección de memoria de una variable, y el operador asterisco para acceder al valor almacenado en esa dirección. Este conocimiento te salva de posibles errores e inconvenientes en el manejo de memoria en Go.
Finalmente, si estás interesado en adquirir un conocimiento más profundo sobre Go, te recomendamos seguir los cursos preliminares disponibles. Continuar explorando programación orientada a objetos es el siguiente paso recomendable para fortalecer tus habilidades de desarrollo en Go. Sigue aprendiendo y mejorando tus proyectos. ¡Nos vemos en la próxima clase!
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?