我是golang的新手,我正在尝试goroutine,虽然它很容易同时运行,但我有点惊讶的是golang to"加入线程"使用WaitGroup
。
据我所知,goroutine需要引用WaitGroup对象来调用Done()
,这意味着,我必须让goroutine接受WaitGroup
对象,或者make { {1}}对象是goroutine的全局对象。
但在像Python这样的其他语言中,你可以调用WaitGroup
,"控制"部分位于线程代码之外。
就像我说的那样,我对golang很新,我不知道为什么会这样设计,有人可以就这方面做些什么吗?
更新: 我希望这个论点不是基于' Goroutine vs Thread',在一天结束时他们都试图实现(某种程度)并发',我的问题更多的是关于控制程序流程。
答案 0 :(得分:5)
为什么它是这样设计的
golang团队实际上已经多次解释过了 - 为什么我们不能杀死goroutines,为什么他们没有我们可以阅读的ID,为什么我们不能像线程{{1}那样明确地等待goroutine }}
有多次解释,但我只能找到this。基本上,作者不希望你依赖于线程局部性 - 锁定特定的线程/ goroutine,只为它拥有本地存储等等。当你没有任何方法可以知道你在哪个goroutine中让你被迫以一种真正的方式设计你的应用程序。您的代码由真正独立的部分组成,这些部分运行得很精确,而且他们并不关心究竟如何。您不关心哪个goroutine选择您的代码,您不关心哪个OS线程正在运行您的代码。这就是频道,精选和其他原语的用武之地。它们可以帮助您以这种方式构建应用程序。我相信它并不止于此。
答案 1 :(得分:3)
不,这只是另一件事,它做了不同的事情。它们甚至不具有可比性,因为WaitGroup
本质上等待多个事物(并且可以在其生命周期中添加内容)和python线程join
总是如此等等那件事。
那就是说,Go的图书馆更多的是为你提供你需要做更高级的事情的原始事物,而Python已经包含更多的电池和#34;哲学。使用Go提供的东西,你可以创建一个类似于python Thread
的类型。它可能不是使用Go的最佳方式,但如果你愿意,你可以使用工具来完成它。然而,标准库并没有标准化这样的事情。
答案 2 :(得分:1)
来自hobbs和creker的答案特别优秀,但我觉得还有更多的话要说。
WaitGroup是管理多个goroutine的 方式的一个非常普遍的概念 - 它在很多情况下肯定是常用的,甚至是惯用的。你知道吗?能够调用thread.join()确实优于在等待早期启动的一堆线程/ goroutines时处理WaitGroups。
但Go的并发模型还有 。
Goroutines专门设计为不拥有所有权或层次结构或句柄的概念。他们是独立,平等和负责结束自己的执行。结合强大的并发原语,Go的模型几乎具有无与伦比的灵活性。
因此,如果您发现自己几乎每次使用goroutine时都使用WaitGroups,那么您可能无法在建模和构建程序时利用并发 - 它&#39 ;你更有可能只是使用goroutines来并行化计算。
为了更直接地回答你的问题,与thread.join()之类的东西相比,WaitGroups相当原始,但是对于Go的并发模型,原始的低级构建块更有用。毕竟,goroutines不是线程,并且它们并不意味着使用完全相同的方式。
答案 3 :(得分:0)
据我所知,goroutine需要引用WaitGroup对象来调用Done(),这意味着,我必须让goroutine接受WaitGroup对象,或者让WaitGroup对象全局到goroutine。
我不同意WaitGroup
与其他语言比较落后一步。我真的很喜欢它的简洁性。但是,我确实同意传递WaitGroup
对象意味着并发逻辑会与您的业务逻辑混合在一起而我不喜欢它。
所以我想出了这个通用函数来解决这个问题:
// Parallelize parallelizes the function calls
func Parallelize(functions ...func()) {
var waitGroup sync.WaitGroup
waitGroup.Add(len(functions))
defer waitGroup.Wait()
for _, function := range functions {
go func(copy func()) {
defer waitGroup.Done()
copy()
}(function)
}
}
以下是一个例子:
func1 := func() {
for char := 'a'; char < 'a' + 3; char++ {
fmt.Printf("%c ", char)
}
}
func2 := func() {
for number := 1; number < 4; number++ {
fmt.Printf("%d ", number)
}
}
Parallelize(func1, func2) // a 1 b 2 c 3
如果您想使用它,可以在https://github.com/shomali11/util
找到它