2015-03-10 6 views
6

Während SayHello() wie erwartet ausgeführt wird, druckt die Goroutine nichts.Keine Ausgabe von Goroutine in Go

package main 

import "fmt" 

func SayHello() { 
    for i := 0; i < 10 ; i++ { 
     fmt.Print(i, " ") 
    } 
} 

func main() { 
    SayHello() 
    go SayHello() 
} 
+0

möglich Duplikat laufen [Goroutine nicht ausgeführt, wenn time.sleep enthalten] (http: // Stackoverflow. com/questions/28307783/goroutine-does-not-execute-wenn-zeit-schlaf-enthalten) –

Antwort

15

Wenn Ihre main()-Funktion endet, endet auch Ihr Programm. Es wartet nicht darauf, dass andere Goroutines zu Ende gehen.

Zitiert aus dem Go Language Specification: Program Execution:

Die Programmausführung beginnt mit dem Hauptpaket initialisiert und dann den Aufruf der Funktion main. Wenn dieser Funktionsaufruf zurückkehrt, wird das Programm beendet. Es wartet nicht darauf, dass andere (nicht main) Goroutines abgeschlossen werden.

Weitere Informationen finden Sie unter this answer.

Sie müssen Ihre main() Funktion zu warten, bis die SayHello() Funktion als Goroutine abgeschlossen zu beenden. Sie können sie mit den Kanälen zum Beispiel synchronisieren:

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 
} 

Eine weitere Alternative ist die Fertigstellung signalisiert durch den Kanal endet:

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 
} 

Hinweise:

nach Ihren Änderungen/Bemerkungen: Wenn Sie möchten, dass die 2 laufenden SayHello() Funktionen "gemischte" Zahlen zufällig drucken: Sie haben keine Garantie, ein solches Verhalten zu beobachten. Siehe auch die aforementioned answer für weitere Details. Die Go Memory Model garantiert nur, dass bestimmte Ereignisse vor anderen Ereignissen passieren, Sie haben keine Garantie, wie 2 gleichzeitige goroutines ausgeführt werden.

Sie könnten damit experimentieren, aber wissen, dass das Ergebnis nicht deterministisch sein wird. Als erstes müssen Sie mehrere aktive goroutines ermöglichen, ausgeführt werden:

runtime.GOMAXPROCS(2) 

Und zweitens müssen Sie zuerst SayHello() als goroutine gestartet werden, da Ihre erste Strom Code SayHello() im Haupt goroutine ausführt und nur sobald es fertig startet die andere ein: Alternativ

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

Richtig, ich habe gerade Ihre Bearbeitung nach dem Lesen verstanden http://dave.cheney.net/2014/03/19/channel- Axiome: Ein Senden an einen 'nil' Kanal blockiert für immer, Ein Empfang von einem' nil' Kanal blockiert für immer. – VonC

+0

@icza bitte überprüfen Sie die Änderungen. –

+0

@DineshPanchananam Was meinst du mit "unorderly" Mode? Sie erwarten zufällig gemischte Zahlen aus den 2 laufenden 'SayHello()' Funktionen? – icza

5

(zu icza Antwort) können Sie WaitGroup aus sync Paket und anonyme Funktion verwenden, um zu vermeiden ursprünglichen SayHello zu verändern.

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

Um Nummern gedruckt werden gleichzeitig jede print-Anweisung in separaten Routine wie folgt

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

Bitte überprüfen Sie die Änderungen –

+0

@DineshPanchananam Möchten Sie jede Nummer in einer separaten Routine drucken? – Sundrique

+0

Nein ich erwarte etwas "" parallel "" ". Aber ich denke, ich bin falsch. –