Почему fmt.Println внутри goroutine не печатает строку?
У меня есть следующий код:
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)
}()
}
Если у меня нет кода, который читается из буфера в goroutine, он выводит такое сообщение, которое я ожидаю:
:zelazny.freenode.net NOTICE * :*** Looking up your hostname...
Однако, если он внутри goroutine ничего не печатает.
Может кто-нибудь объяснить, почему это?
Ответы
Ответ 1
Ваша программа выйдет, когда закончится функция main()
. Вероятно, это произойдет до того, как ваш goroutine успеет запустить и распечатать свой результат.
Один из вариантов заключается в том, чтобы чтение основного блока goroutine с канала, и чтобы goroutine записывался на канал, когда он завершил свою работу.
Ответ 2
Другим распространенным способом, который вы увидите в ожидании завершения goroutines, является http://golang.org/pkg/sync/#WaitGroup. вы можете waitGroup.Add(1)
для каждого запуска goroutine, затем waitGroup.Done()
в goroutine после его завершения, а main может waitGroup.Wait()
, и он будет блокироваться до тех пор, пока waitGroup.Done()
не будет вызван для каждого Add.
Ответ 3
Запись данных в канал ch
в конце goroutine и чтение данных из ch
из goroutine может сделать основную функцию ожидающей сообщения goroutine print.
Вот пример:
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
}
Ответ 4
Как указано выше, функция main() будет завершена до того, как у goroutine появится шанс запустить. Горутины как легкие потоки работают в свое время. С целью отладки трюка, который я обычно использую, нужно добавить сон сразу после моего goroutine, достаточно долго, чтобы он позволил моему goroutine закончить. Вот очень простой пример:
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println("Hello gopher!")
go print_nums(10)
time.Sleep(time.Millisecond * 100) // if i take this line out all i will see is hello and bye gopher!
fmt.Println("Bye gopher!")
}
func print_nums(num int) {
i := 0
for i < num {
fmt.Println(i)
i++
}
}
Ответ 5
Вам нужно добавить задержку времени, например time.Sleep(3 * time.Second)
(это ждет 3 секунды).
Горотин закрывается, когда программа завершается. У меня была такая же проблема.