第一个 goroutine 示例,结果很奇怪

huangapple go评论127阅读模式
英文:

First goroutine example, weird results

问题

这个例子来自tour.golang.org/#63

<!-- 注释因为编辑必须超过6个字符 -->

  1. package main
  2. import (
  3. "fmt"
  4. "time"
  5. )
  6. func say(s string) {
  7. for i := 0; i < 5; i++ {
  8. time.Sleep(100 * time.Millisecond)
  9. fmt.Println(s)
  10. }
  11. }
  12. func main() {
  13. go say("world")
  14. say("hello")
  15. }

输出结果

  1. hello
  2. world
  3. hello
  4. world
  5. hello
  6. world
  7. hello
  8. world
  9. hello

为什么world只打印了4次而不是5次?


编辑: 答案可以从golang规范中引用:

> 程序的执行从初始化主包开始,然后调用main函数。当main函数返回时,程序退出。它不会等待其他(非主)goroutine完成。

英文:

This example taken from tour.golang.org/#63
<!-- comment because edit must be more than 6 chars -->

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. &quot;time&quot;
  5. )
  6. func say(s string) {
  7. for i := 0; i &lt; 5; i++ {
  8. time.Sleep(100 * time.Millisecond)
  9. fmt.Println(s)
  10. }
  11. }
  12. func main() {
  13. go say(&quot;world&quot;)
  14. say(&quot;hello&quot;)
  15. }

The output

  1. hello
  2. world
  3. hello
  4. world
  5. hello
  6. world
  7. hello
  8. world
  9. hello

Why world is printed only 4 times instead of 5 ?


Edit: The answer can be quoted from golang specification:

> Program execution begins by initializing the main package and then
> invoking the function main. When the function main returns, the
> program exits. It does not wait for other (non-main) goroutines to
> complete.

答案1

得分: 5

当你的主函数结束时,程序也会结束,也就是说所有的goroutine都会被终止。
go say("world")完成之前,你的主函数就已经终止了。如果你在主函数的末尾加上一些睡眠时间,你应该能看到最后的"world"。

英文:

When your main function ends your program ends, i.e. all goroutines are terminated.
Your main terminates before go say(&quot;world&quot;) is done. If you sleep some time at the end of main you should see the last world.

答案2

得分: 4

这是如何正确解决同步问题的方法 - 使用sync.WaitGroup

Playground链接

  1. package main
  2. import (
  3. "fmt"
  4. "sync"
  5. "time"
  6. )
  7. func say(s string, wg *sync.WaitGroup) {
  8. defer wg.Done()
  9. for i := 0; i < 5; i++ {
  10. time.Sleep(100 * time.Millisecond)
  11. fmt.Println(s)
  12. }
  13. }
  14. func main() {
  15. wg := new(sync.WaitGroup)
  16. wg.Add(2)
  17. go say("world", wg)
  18. go say("hello", wg)
  19. wg.Wait()
  20. fmt.Println("All done")
  21. }
英文:

Here is how you solve that synchronization problem properly - with sync.WaitGroup

Playground link

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. &quot;sync&quot;
  5. &quot;time&quot;
  6. )
  7. func say(s string, wg *sync.WaitGroup) {
  8. defer wg.Done()
  9. for i := 0; i &lt; 5; i++ {
  10. time.Sleep(100 * time.Millisecond)
  11. fmt.Println(s)
  12. }
  13. }
  14. func main() {
  15. wg := new(sync.WaitGroup)
  16. wg.Add(2)
  17. go say(&quot;world&quot;, wg)
  18. go say(&quot;hello&quot;, wg)
  19. wg.Wait()
  20. fmt.Println(&quot;All done&quot;)
  21. }

答案3

得分: 2

因为调用的goroutine在你创建的第二个goroutine之前终止,这导致第二个goroutine关闭。为了说明这一点,稍微修改一下你的代码:

  1. package main
  2. import (
  3. "fmt"
  4. "time"
  5. )
  6. func say(s string) {
  7. for i := 0; i < 5; i++ {
  8. time.Sleep(100 * time.Millisecond)
  9. fmt.Print(i)
  10. fmt.Println(":" + s)
  11. }
  12. }
  13. func main() {
  14. go say("world")
  15. say("hello")
  16. time.Sleep(1 * time.Second) // 在main函数的末尾加上一个等待或者睡眠
  17. }

在main函数的末尾加上一个等待或者睡眠的操作。

英文:

Because the calling gorouting terminates before the second one you spawned does. This causes the second to shut down. To illustrate, modify your code slightly:

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. &quot;time&quot;
  5. )
  6. func say(s string) {
  7. for i := 0; i &lt; 5; i++ {
  8. time.Sleep(100 * time.Millisecond)
  9. fmt.Print(i)
  10. fmt.Println(&quot;:&quot;+s)
  11. }
  12. }
  13. func main() {
  14. go say(&quot;world&quot;)
  15. say(&quot;hello&quot;)
  16. }

Try putting in a "wait" or a sleep to the end of the main function.

huangapple
  • 本文由 发表于 2013年9月4日 03:20:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/18599875.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定