2015-03-10 17 views
6

Mentre SayHello() si esegue come previsto, la goroutine non stampa nulla.Nessun output da goroutine in Go

+0

possibile duplicato del [goroutine non esegue se time.sleep inclusa] (http: // StackOverflow. it/questions/28307783/goroutine-does-not-execute-if-time-sleep-incluso) –

risposta

15

Quando la funzione main() termina, anche il programma termina. Non aspetta che le altre goroutine finiscano.

Citando dalla Go Language Specification: Program Execution:

L'esecuzione del programma inizia inizializzando il pacchetto principale e quindi invocando la funzione main. Al termine di tale chiamata, il programma termina. Non attende altre goreutine (non main) da completare.

Vedere this answer per ulteriori dettagli.

Devi dire alla tua funzione main() di aspettare che la funzione SayHello() sia stata avviata come una goroutine da completare. È possibile eseguire la sincronizzazione con canali ad esempio:

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 
} 

Un'altra alternativa è quella di segnalare il completamento chiudendo il canale:

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 
} 

Note:

Secondo le modifiche/commenti: se si desidera che le 2 funzioni in esecuzione SayHello() stampino in modo casuale numeri "misti": non si ha alcuna garanzia di osservare tale comportamento. Ancora una volta, vedi lo aforementioned answer per maggiori dettagli. Lo Go Memory Model garantisce solo che determinati eventi si verifichino prima di altri eventi, non si ha alcuna garanzia di come vengano eseguite 2 goroutine concorrenti.

Si potrebbe sperimentare, ma sapere che il risultato non sarà deterministico. In primo luogo si deve consentire a più goroutines attivi da eseguire con:

runtime.GOMAXPROCS(2) 

E in secondo luogo si deve iniziare prima SayHello() come goroutine perché il codice attuale eseguito per primo SayHello() nella goroutine principale e solo una volta è finito inizia l'altra uno:

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 
+1

Giusto, ho appena capito la tua modifica dopo aver letto http://dave.cheney.net/2014/03/19/channel- assiomi: Un invio ai blocchi di canale 'nil' per sempre, Una ricezione da blocchi di canale' nil' per sempre. – VonC

+0

@ icza per favore controlla le modifiche. –

+0

@DineshPanchananam Cosa intendi per moda "disordinata"? Ti aspetti di vedere numeri misti casualmente dalle 2 funzioni 'SayHello()' in esecuzione? – icza

5

alternativa (alla risposta di icza) si possono usare WaitGroup da sync confezione e funzione anonima per non alterare originale 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() 
} 

Per stampare i numeri contemporaneamente eseguire ogni istruzione di stampa nella routine separata come il seguente

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() 
} 
+0

per favore controlla le modifiche –

+0

@DineshPanchananam vuoi stampare ogni numero in una routine separata? – Sundrique

+0

No. mi aspettavo qualcosa "" parallelo "" "., Ma penso di essermi sbagliato –

Problemi correlati