运行 代码与 goroutine 并行的首选语法是什么?

What is the preferred syntax to run code in parallel with goroutine?

假设我需要调用一个函数两次。通常的做法是:

func main() {
    var wg sync.WaitGroup
    wg.Add(2)

    go func() {
        doSomething(A)          
        wg.Done()
    }()

    go func() {
        doSomething(B)
        wg.Done()
    }()
    wg.Wait()
}

但是这样写呢?

func main() {
    var wg sync.WaitGroup
    wg.Add(2)

    go func() {
        doSomething(A)          
        wg.Done()
    }()

    doSomething(B)
    wg.Done()
    wg.Wait()
}

我们节省了创建一个 goroutine 的时间,同时使用了 main goroutine。但是我从来没有在任何教程中看到过这样写的。这样做错了吗?我已经做了测试,输出结果和我一样。

两者都是正确的。如果您打算稍后扩展您的代码,例如,第一种形式更清晰并且可以很好地扩展。如果您稍后决定要启动的不是 2 个而是 3 个或 4 个或 N 个 goroutine,代码的结构不会改变,您只需添加额外的 goroutine。

第一种形式是 "popular" 的另一个原因是因为通常在启动 "worker" goroutines 之后有更多的事情要做,可以在这个 goroutine 上执行(在 wg.Done() 之前称为)。

另一方面,第二种形式更高效,因为它只启动一个额外的 goroutine。 Goroutines 是轻量级的,廉价的,但它们不是 "free"。这可以通过使用 WaitGroup 仅 "track" 启动的 goroutine 来进一步改进,显然调用 wg.Wait() 的 "main" 不需要明确地等待自己。如果只剩下 1 个 goroutine,您可以使用其他同步方式而不是 WaitGroup(例如通道)。

所以基本上,如果性能很重要,请使用第二种方法。