No hay salida de goroutine
Si bien SayHello()
se ejecuta como se esperaba, la rutina no imprime nada.
package main
import "fmt"
func SayHello() {
for i := 0; i < 10 ; i++ {
fmt.Print(i, " ")
}
}
func main() {
SayHello()
go SayHello()
}
Cuando main()
finaliza su función, su programa también finaliza. No espera a que finalicen otras rutinas.
Citando la especificación de Go Language: Ejecución del programa :
La ejecución del programa comienza inicializando el paquete principal y luego invocando la función
main
. Cuando regresa la invocación de esa función, el programa sale. No espera a quemain
se completen otras (no) rutinas.
Consulte esta respuesta para obtener más detalles.
Debe decirle a su main()
función que espere a SayHello()
que se complete la función iniciada como una rutina. Puedes sincronizarlos con canales por ejemplo:
func SayHello(done chan int) {
for i := 0; i < 10; i++ {
fmt.Print(i, " ")
}
if done != nil {
done <- 0 // Signal that we're done
}
}
func main() {
SayHello(nil) // Passing nil: we don't want notification here
done := make(chan int)
go SayHello(done)
<-done // Wait until done signal arrives
}
Otra alternativa es señalar la finalización cerrando el canal:
func SayHello(done chan struct{}) {
for i := 0; i < 10; i++ {
fmt.Print(i, " ")
}
if done != nil {
close(done) // Signal that we're done
}
}
func main() {
SayHello(nil) // Passing nil: we don't want notification here
done := make(chan struct{})
go SayHello(done)
<-done // A receive from a closed channel returns the zero value immediately
}
Notas:
Según sus ediciones/comentarios: si desea que las 2 SayHello()
funciones en ejecución impriman números "mixtos" al azar: no tiene garantía de observar tal comportamiento. Nuevamente, consulte la respuesta antes mencionada para obtener más detalles. El modelo Go Memory solo garantiza que ciertos eventos sucedan antes que otros, no tiene garantía de cómo se ejecutan 2 gorutinas simultáneas.
Puedes experimentar con ello, pero debes saber que el resultado no será determinista. Primero debe habilitar la ejecución de múltiples rutinas activas con:
runtime.GOMAXPROCS(2)
Y en segundo lugar, primero debe comenzar SayHello()
como una rutina porque su código actual se ejecuta primero SayHello()
en la rutina principal y solo una vez que finaliza inicia la otra:
runtime.GOMAXPROCS(2)
done := make(chan struct{})
go SayHello(done) // FIRST START goroutine
SayHello(nil) // And then call SayHello() in the main goroutine
<-done // Wait for completion
Alternativamente (a la respuesta de icza), puede usar WaitGroup
from sync
paquete y función anónima para evitar alterar el original SayHello
.
package main
import (
"fmt"
"sync"
)
func SayHello() {
for i := 0; i < 10; i++ {
fmt.Print(i, " ")
}
}
func main() {
SayHello()
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
SayHello()
}()
wg.Wait()
}
Para imprimir números simultáneamente, ejecute cada declaración de impresión en una rutina separada como la siguiente
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
func main() {
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(fnScopeI int) {
defer wg.Done()
// next two strings are here just to show routines work simultaneously
amt := time.Duration(rand.Intn(250))
time.Sleep(time.Millisecond * amt)
fmt.Print(fnScopeI, " ")
}(i)
}
wg.Wait()
}