patterns golang go concurrency channel goroutine

golang - Goroutine no se ejecuta si se incluye el tiempo.



golang channels (1)

El siguiente código funciona perfectamente bien:

package main import ( "fmt" ) func my_func(c chan int){ fmt.Println(<-c) } func main(){ c := make(chan int) go my_func(c) c<-3 }

playgound_1

Sin embargo si cambio

c<-3

a

time.Sleep(time.Second) c<-3

playground_2

Mi código no se ejecuta.

Mi intuición es que de alguna manera main regresa antes de que my_func termine de ejecutarse, pero parece que agregar una pausa no debería tener ningún efecto. Estoy totalmente perdido en este simple ejemplo, ¿qué está pasando aquí?


Cuando termina la función main , el programa termina con ella. No espera a que otras gorutinas terminen.

Citando desde el Go Idioma Especificación: Ejecución del programa :

La ejecución del programa comienza inicializando el paquete principal y luego invocando la función main . Cuando la invocación de esa función regresa, el programa sale. No espera a que se completen otras gorutinas (no main ).

Entonces, simplemente cuando su función main tiene éxito al enviar el valor en el canal, el programa puede finalizar inmediatamente, antes de que la otra rutina tenga la oportunidad de imprimir el valor recibido en la consola.

Si desea asegurarse de que el valor se imprima en la consola, debe sincronizarlo con el evento de salir de la función main :

Ejemplo con un canal "hecho" (pruébelo en Go Playground ):

func my_func(c, done chan int) { fmt.Println(<-c) done <- 1 } func main() { c := make(chan int) done := make(chan int) go my_func(c, done) time.Sleep(time.Second) c <- 3 <-done }

Dado que done también es un canal sin búfer, recibirlo al final de la función main debe esperar el envío de un valor en el canal done , lo que sucede después de que el valor enviado en el canal c ha sido recibido e impreso en la consola.

Explicación de las corridas aparentemente no deterministas:

Las goroutinas pueden o no ejecutarse en paralelo al mismo tiempo . La sincronización asegura que ciertos eventos sucedan antes que otros eventos. Esa es la única garantía que obtienes, y la única cosa en la que debes confiar. 2 ejemplos de esto sucede antes :

  • La declaración go que inicia una nueva rutina se produce antes de que comience la ejecución de la rutina.
  • Un envío en un canal ocurre antes de que se complete la recepción correspondiente de ese canal.

Para más detalles, lea El modelo de memoria Go .

Regresando a su ejemplo:

Una recepción de un canal sin búfer ocurre antes de que se complete el envío en ese canal.

Entonces, la única garantía que obtienes es que la rutina que ejecuta my_func() recibirá el valor del canal c enviado desde main() . Pero una vez que se recibe el valor, la función main puede continuar, pero como no hay más declaraciones después del envío, simplemente finaliza, junto con el programa. Si la gorutina no main tendrá tiempo u oportunidad de imprimirla con fmt.Println() no está definida .