Need understanding of goroutines

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

Need understanding of goroutines

问题

我是你的中文翻译助手,以下是你提供的代码的翻译:

我是Go语言编程的新手,正在逐步学习。在练习过程中,我发现goroutine的行为是随机的。如果我调用一个包含1秒睡眠的goroutine函数,有时它会成功完成,有时则不会:

package main

import (
	"fmt"
	"time"
)

func t(i int) {
	fmt.Println("In func t")
	time.Sleep(1)
}

func t1(i int) {
	fmt.Println("In func t1")
	time.Sleep(1)
}

func main() {
	fmt.Println("Hello Good Morning")
	go t(1)
	t1(2)
	time.Sleep(5)
	fmt.Println("End of func main")
}

输出1:

Hello Good Morning
In func t1
In func t
End of func main

输出2:

Hello Good Morning
In func t1
End of func main

有人能解释一下为什么goroutine不能保证执行该goroutine函数调用吗?

英文:

I am new to Go language programming and learning it step by step.
While practicing it, I found random behavior of goroutines.
If I call goroutine (function having sleep of 1 second), some times it completed successfully and some times it doesn't:

package main

import (
	"fmt"
	"time"
)

func t(i int) {
	fmt.Println("In func t")
	time.Sleep(1)
}

func t1(i int) {
	fmt.Println("In func t1")
	time.Sleep(1)
}

func main() {
	fmt.Println("Hello Good Morning")
	go t(1)
	t1(2)
	time.Sleep(5)
	fmt.Println("End of func main")
}

O/p 1 :

  Hello Good Morning
  In func t1
  In func t
  End of func main

O/p 2 :

  Hello Good Morning
  In func t1
  End of func main

Could someone explain why goroutine is not guaranteeing the execution of that goroutine function call.

答案1

得分: 1

程序执行

当函数main返回时,程序退出。它不会等待其他(非主)goroutine完成。

1- main也是一个goroutine,你需要等待其他goroutine完成,你可以使用

time.Sleep(5 * time.Second)

等待5秒钟,可以在Go Playground上尝试一下:

package main

import (
    "fmt"
    "time"
)

func t(i int) {
    fmt.Println("In func t")
    time.Sleep(1 * time.Second)
}

func t1(i int) {
    fmt.Println("In func t1")
    time.Sleep(1 * time.Second)
}

func main() {
    fmt.Println("Hello Good Morning")
    go t(1)
    t1(2)
    time.Sleep(5 * time.Second)
    fmt.Println("End of func main")
}

输出:

Hello Good Morning
In func t1
In func t
End of func main

并查看文档:

// Sleep暂停当前的goroutine,至少持续时间为d。
// 负数或零的持续时间会导致Sleep立即返回。
func Sleep(d Duration)

2- 你可以使用sync.WaitGroup等待其他goroutine完成,可以在Go Playground上尝试一下:

package main

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

var w sync.WaitGroup

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

func main() {
    w.Add(1)
    go say("A")

    w.Add(1)
    say("B")

    w.Wait()
}

输出:

B
A
A
B
英文:

Program execution:

> When the function main returns, the program exits. It does not wait
> for other (non-main) goroutines to complete.

1- main is goroutine too, you need to wait for other goroutines to finish, and you may use

time.Sleep(5 * time.Second)

for 5 Seconds wait, try it on The Go Playground:

package main

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

func t(i int) {
	fmt.Println(&quot;In func t&quot;)
	time.Sleep(1 * time.Second)
}

func t1(i int) {
	fmt.Println(&quot;In func t1&quot;)
	time.Sleep(1 * time.Second)
}

func main() {
	fmt.Println(&quot;Hello Good Morning&quot;)
	go t(1)
	t1(2)
	time.Sleep(5 * time.Second)
	fmt.Println(&quot;End of func main&quot;)
}

output:

Hello Good Morning
In func t1
In func t
End of func main

And see Docs:

> // Sleep pauses the current goroutine for at least the duration d.
> // A negative or zero duration causes Sleep to return immediately.
> func Sleep(d Duration)


2- You may use sync.WaitGroup to wait for other goroutines, try it on The Go Playground:

package main

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

var w sync.WaitGroup

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

func main() {
	w.Add(1)
	go say(&quot;A&quot;)

	w.Add(1)
	say(&quot;B&quot;)

	w.Wait()
}

output:

B
A
A
B

答案2

得分: 0

两件事情:

  1. 如果你在main函数中没有显式等待goroutine完成,那么不能保证它会在程序退出之前完成。
  2. time.Sleep()的参数类型是time.Duration,单位是纳秒。由于你几乎没有延迟,所以结果是随机的也就不足为奇了。如果你在main函数中睡眠更长的时间,你应该会看到两行都被打印出来(尽管不能保证)。

如果你需要等待goroutine完成,有多种方法可以实现(例如使用通道和sync.WaitGroup)。

你可以参考一下《Go语言之旅》1,或者查看《Effective Go》2

英文:

Two things:

  1. If you return from main without having explicitly waited for your
    goroutine to finish, there's no guarantee that it will finish before
    the program exits.
  2. The argument type of time.Sleep() is time.Duration,
    the units of which are nanoseconds. Since you're barely delaying at
    all, it's not surprising that your results were random. If you sleep
    for a more substantial amount of time in main, you should see both
    lines printed (although it isn't guaranteed).

If you need to wait for a goroutine to finish, there are various ways to do that (e.g, channels and sync.WaitGroup).

You may want to go through A Tour of Go and/or take a look at Effective Go.

huangapple
  • 本文由 发表于 2016年10月25日 11:49:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/40231069.html
匿名

发表评论

匿名网友

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

确定