多个sync.WaitGroup的用法

时间:2018-12-15 10:48:24

标签: pointers go concurrency

我看到了sync.WaitGroup

的一些不同示例

示例1

var wg sync.WaitGroup

wg.Add(1)
go doStuff(&wg)
wg.Wait()

示例2

wg := new(sync.WaitGroup)

wg.Add(1)
go doStuff(wg)
wg.Wait()

区别实际上是sync.WaitGroup的初始化方式 varnew

如果使用var选项,则必须将其作为指针&wg传递到goroutine,但是如果我使用new选项,则可以将其作为wg发送< / p>

两个示例之间有什么区别?以上2个中的哪一个是正确的?在某些情况下,一个优先于另一个吗?

我正在编写一个可以创建多个sync.WaitGroup的程序,那么使用new还是var是否重要?

1 个答案:

答案 0 :(得分:3)

您的两个示例均正常工作。另外请注意,除了new()之外,您还可以使用composite literal并使用其地址,如下所示:

var wg = &sync.WaitGroup{}

sync.WaitGroup的方法具有指针接收器,因此,每当调用其方法时,都需要WaitGroup结构值的地址。这不是问题,因为当wg是非指针时,wg.Add(1)wg.Done()的调用是(&wg).Add(1)(&wg).Done()的简写,因此编译器自动“重写”这些调用以首先获取wg的地址,并将该地址用作方法的接收者。

但是,我仍然认为,如果值仅用作指针(sync.WaitGroup是一个光辉的示例),则应声明该值并首先将其用作指针,这样可以减少使用错误的余地。

例如,如果您使用非指针,并且声明该函数期望非指针,并且将其作为非指针传递,则不会出现编译时错误,但会产生错误行为({ {1}}不应被复制。)

尽管今天的短毛猫会给您一个警告消息,但是,我认为最好始终使用指针。

使用指针的另一个原因:如果函数将返回sync.WaitGroup,或者如果您有一个将sync.WaitGroup存储为值的映射,则您将无法在结果上调用方法,因为函数的返回值和映射索引操作是不可寻址的。如果函数将返回指针值,或者首先将指针存储在映射中,则仍然可以调用方法而不必将其存储在局部变量中。有关详细信息,请参见How can I store reference to the result of an operation in Go?

例如:

sync.WaitGroup

但是这些工作:

func getWg() sync.WaitGroup { return sync.WaitGroup{} }

getWg().Wait() // Compile-time error!

m := map[int]sync.WaitGroup{
    1: sync.WaitGroup{},
}

m[1].Wait() // Again: compile-time error

在此处详细了解此内容:Why should constructor of Go return address?