¿Cómo comunicar canales en Go?
Ahora vamos a volver a utilizar el ejemplo anterior en donde simulamos la lectura de un archivo grande.
package main
import (
"fmt"
"time"
)
func leerArchivo() string {
time.Sleep(time.Second * 5)
return "Datos del archivo"
}
func main() {
go func() {
datos := leerArchivo()
fmt.Println(datos)
}()
fmt.Println("Continuar con la ejecución")
time.Sleep(time.Second * 10)
}
Vamos a reemplazar el bloqueo de 10 segundos, por uno que solo espera a que la rutina se complete.
package main
import (
"fmt"
"time"
)
func leerArchivo() string {
time.Sleep(time.Second * 2)
return "Datos del archivo"
}
func main() {
miCanal := make(chan string)
go func() {
miCanal <- leerArchivo()
}()
fmt.Println(<-miCanal)
fmt.Println("Continuar con la ejecución")
}
Si ejecutamos el script, el resultado es el mismo, la diferencia es que en lugar de bloquear mediante un sleep, nuestro programa se bloquea en cuanto a miCanal
se le asigna un valor.
Para crear un canal de tipo string, es decir que reciba este tipo de valores utilizamos la instrucción:
miCanal := make(chan string)
Lo siguiente que sucede, es que el programa ejecuta una rutina en segundo plano, que asigna un valor al canal unos segundos después, cuando se lee de forma completa el archivo.
go func() {
miCanal <- leerArchivo()
}()
Pero antes que esto suceda, se ha intentado leer un valor del canal.
fmt.Println(<-miCanal)
Al no tener un valor aun asignado, el programa genera un bloqueo, que solo se libera cuando el canal recibe un valor… en este caso dentro de la rutina.