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

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

First goroutine example, weird results

问题

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

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

package main

import (
	"fmt"
	"time"
)

func say(s string) {
	for i := 0; i < 5; i++ {
		time.Sleep(100 * time.Millisecond)
		fmt.Println(s)
	}
}

func main() {
	go say("world")
	say("hello")
}

输出结果

hello
world
hello
world
hello
world
hello
world
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 -->

package main

import (
	&quot;fmt&quot;
	&quot;time&quot;
)

func say(s string) {
	for i := 0; i &lt; 5; i++ {
		time.Sleep(100 * time.Millisecond)
		fmt.Println(s)
	}
}

func main() {
	go say(&quot;world&quot;)
	say(&quot;hello&quot;)
}

The output

hello
world
hello
world
hello
world
hello
world
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链接

package main

import (
	"fmt"
	"sync"
	"time"
)

func say(s string, wg *sync.WaitGroup) {
	defer wg.Done()
	for i := 0; i < 5; i++ {
		time.Sleep(100 * time.Millisecond)
		fmt.Println(s)
	}
}

func main() {
	wg := new(sync.WaitGroup)
	wg.Add(2)
	go say("world", wg)
	go say("hello", wg)
	wg.Wait()
	fmt.Println("All done")
}
英文:

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

Playground link

package main

import (
	&quot;fmt&quot;
	&quot;sync&quot;
	&quot;time&quot;
)

func say(s string, wg *sync.WaitGroup) {
	defer wg.Done()
	for i := 0; i &lt; 5; i++ {
		time.Sleep(100 * time.Millisecond)
		fmt.Println(s)
	}
}

func main() {
	wg := new(sync.WaitGroup)
	wg.Add(2)
	go say(&quot;world&quot;, wg)
	go say(&quot;hello&quot;, wg)
	wg.Wait()
	fmt.Println(&quot;All done&quot;)
}

答案3

得分: 2

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

package main

import (
    "fmt"
    "time"
)

func say(s string) {
    for i := 0; i < 5; i++ {
        time.Sleep(100 * time.Millisecond)
        fmt.Print(i)
        fmt.Println(":" + s)
    }
}

func main() {
    go say("world")
    say("hello")
    time.Sleep(1 * time.Second) // 在main函数的末尾加上一个等待或者睡眠
}

在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:

package main

import (
    &quot;fmt&quot;
    &quot;time&quot;
)

func say(s string) {
    for i := 0; i &lt; 5; i++ {
        time.Sleep(100 * time.Millisecond)
        fmt.Print(i)
        fmt.Println(&quot;:&quot;+s)
    }
}

func main() {
    go say(&quot;world&quot;)
    say(&quot;hello&quot;)
}

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:

确定