为什么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里面,什么也不打印。
有人可以解释为什么吗?
main()
函数完成后,程序将退出。 这可能发生在您的goroutine有时间运行并打印输出之前。
一种select是让主要的goroutine块从一个频道读取,并在完成其工作时将该goroutine写入频道。
另一个常见的等待goroutines完成的方法是http://golang.org/pkg/sync/#WaitGroup 。 你可以为每个goroutine启动waitGroup.Add(1)
,然后在goroutine完成后waitGroup.Wait()
,而main可以waitGroup.Wait()
,它会阻塞,直到waitGroup.Done()
被调用每个添加。
在goroutine结束时将数据写入通道ch
,从goroutine中读取数据可以使main函数等待goroutine打印消息。
这里是一个例子:
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 }
如上所述,main()函数将在goroutine有机会运行之前退出。 Goroutines作为轻量级线程运行在自己的时间。 为了debugging我通常使用的技巧,就是在我的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++ } }
您需要添加像time.Sleep(3 * time.Second)
(这等待3秒)的时间延迟。
当程序终止时,goroutineclosures。 我有同样的问题。