如何将 WaitGroup 传递给顺序函数调用?

Son*_*sar 1 concurrency go waitgroup

我有一个可以在单独的 goroutine 中顺序或同时调用的函数。

我想确保该函数在主 goroutine 完成之前完全执行,因此我将 *sync.WaitGroup 参数传递给该函数。现在,在某些地方该函数将被顺序调用。

我可以将 nil waitGroup 传递给函数,如下所示:

func my_func(wg *sync.WaitGroup){
   if wg != nil{
   defer wg.Done()
   }
   // do the task
}

func main(){
my_func(nil) // sequential call

wg := sync.WaitGroup{}
wg.Add(1)
go my_func(&wg)  // concurrent call
wg.Wait()
}
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法来实现这一目标?

icz*_*cza 7

my_func()不应该知道/不应该关心它是如何执行的(无论是否在新的 goroutine 中)。所以仅仅为了这个你就不应该通过wg。不要强制并发或非并发使用您的 API,让您的包的用户决定他们希望如何调用它。

如果有人希望在新的 goroutine 中同时运行它,可以像这样在外部wg处理:my_func()

wg.Add(1)
go func() {
    defer wg.Done()
    my_func()
}()
Run Code Online (Sandbox Code Playgroud)

这也使得可以在函数调用之前/之后放置更多代码,这些代码将在调用之前执行wg.Done()

wg.Add(1)
go func() {
    defer wg.Done()

    // other code before
    my_func()
    // other code after
}()
Run Code Online (Sandbox Code Playgroud)

另请注意,如果在很多地方都有此功能,则可以创建一个辅助函数来负责 goroutine 启动和 waitgroup 处理:

func launchMyFunc(wg *sync.WaitGroup) {
    go func() {
        defer wg.Done()

        my_func()
    }()
}
Run Code Online (Sandbox Code Playgroud)

您还可以创建一个接受任意无参数无返回函数的帮助器:

func launchFunc(wg *sync.WaitGroup, f func()) {
    go func() {
        defer wg.Done()

        f()
    }()
}
Run Code Online (Sandbox Code Playgroud)

使用上面的助手,你可以这样做:

wg.Add(1)
launchMyFunc(wg)

// or
wg.Add(1)
launchFunc(wg, my_func)
Run Code Online (Sandbox Code Playgroud)