Warum druckt fmt.Println in einer Goroutine keine Zeile?

70

Ich habe folgenden Code:

package main

import "net"
import "fmt"
import "bufio"

func main() {
    conn, _ := net.Dial("tcp", "irc.freenode.net:6667")

    reader := bufio.NewReader(conn)
    go func() {
        str, err := reader.ReadString('\n')
        if err != nil {
            // handle it
            fmt.Println(err)
        }
        fmt.Println(str)
    }()

}

Wenn ich nicht den Code habe, der in einer Goroutine aus dem Puffer liest, gibt er eine Nachricht wie diese aus, was ich erwarte:

:zelazny.freenode.net NOTICE * :*** Looking up your hostname...

Wenn Sie es jedoch in einer Goroutine haben, wird nichts gedruckt.

Kann jemand erklären, warum das so ist?

Ryan Bigg
quelle

Antworten:

79

Ihr Programm wird beendet, wenn die main()Funktion beendet ist. Dies ist wahrscheinlich, bevor Ihre Goroutine Zeit hat, ihre Ausgabe auszuführen und zu drucken.

Eine Möglichkeit wäre, den Haupt-Goroutine-Block von einem Kanal lesen zu lassen und die Goroutine nach Abschluss ihrer Arbeit in den Kanal schreiben zu lassen.

James Henstridge
quelle
2
Danke für die tolle Erklärung, James. Ich denke definitiv, dass Kanäle das sind, wonach ich suche.
Ryan Bigg
36

Eine andere übliche Methode, um "auf das Ende der Goroutinen zu warten", ist die Verwendung von WaitGroup: http://golang.org/pkg/sync/#WaitGroup . Sie können waitGroup.Add(1)für jede gestartete Goroutine verwenden und dann waitGroup.Done()in jeder Goroutine verwenden, nachdem sie beendet ist. In der Hauptfunktion können Sie verwenden waitGroup.Wait()und dies wird warten, bis waitGroup.Done()für jede hinzugefügte Goroutine aufgerufen wurde.

Erik St. Martin
quelle
Danke fürs Teilen, Erik.
Ryan Bigg
3

Schreiben Sie Daten in einen Kanal cham Ende der Goroutine und lesen Sie Daten von chaußerhalb der Goroutine. Dadurch kann die Hauptfunktion auf die Goroutine-Drucknachricht warten.

Hier ist ein Beispiel:

package main

import "net"
import "fmt"
import "bufio"

func main() {
conn, _ := net.Dial("tcp", "irc.freenode.net:6667")

reader := bufio.NewReader(conn)
ch := make(chan byte, 1)
go func() {
    str, err := reader.ReadString('\n')
    if err != nil {
        // handle it
        fmt.Println(err)
    }
    fmt.Println(str)
    ch <- 1
  }()
  <-ch
}
robothy
quelle
-9

Sie müssen eine Zeitverzögerung wie hinzufügen time.Sleep(3 * time.Second)(dies wartet 3 Sekunden).

Die Goroutine wird geschlossen, wenn das Programm beendet wird. Ich hatte genau das gleiche Problem.

Liam
quelle