¿Por qué no es posible obtener un valor de retorno de una goroutine asignándolo a una variable?
Ejecutar goroutine (asincrónicamente) y obtener el valor de retorno de la función son acciones esencialmente contradictorias. Cuando dice go
que quiere decir "hacerlo asincrónicamente" o incluso más simple: "¡Adelante! No espere a que finalice la ejecución de la función". Pero cuando asigna un valor de retorno de función a una variable, espera tener este valor dentro de la variable. Entonces, cuando haces eso, x := go doSomething(arg)
estás diciendo: "¡Continúa, no esperes la función! ¡Espera-espera-espera! ¡Necesito que se pueda acceder a un valor devuelto en x
var en la siguiente línea!"
Canales
La forma más natural de obtener un valor de una gorutina son los canales. Los canales son las tuberías que conectan gorutinas concurrentes. Puede enviar valores a canales desde una goroutine y recibir esos valores en otra goroutine o en una función sincrónica. Puede obtener fácilmente un valor de una goroutine que no rompa la concurrencia usando select
:
func main() {
c1 := make(chan string)
c2 := make(chan string)
go func() {
time.Sleep(time.Second * 1)
c1 <- "one"
}()
go func() {
time.Sleep(time.Second * 2)
c2 <- "two"
}()
for i := 0; i < 2; i++ {
select {
case msg1 := <-c1:
fmt.Println("received", msg1)
case msg2 := <-c2:
fmt.Println("received", msg2)
}
}
}
El ejemplo está tomado de Go By Example
CSP y transmisión de mensajes
Go se basa en gran medida en la teoría CSP . La descripción ingenua de arriba podría describirse con precisión en términos de CSP (aunque creo que está fuera del alcance de la pregunta). Recomiendo encarecidamente familiarizarse con la teoría de la CSP al menos porque es RAD. Estas breves citas dan una dirección de pensamiento:
Como su nombre indica, CSP permite la descripción de sistemas en términos de procesos componentes que operan de forma independiente e interactúan entre sí únicamente a través de la comunicación de paso de mensajes .
En informática, el paso de mensajes envía un mensaje a un proceso y se basa en el proceso y la infraestructura de apoyo para seleccionar e invocar el código real para su ejecución. El paso de mensajes difiere de la programación convencional donde un proceso, subrutina o función se invoca directamente por su nombre.