我看到了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
的初始化方式
var
与new
如果使用var
选项,则必须将其作为指针&wg
传递到goroutine,但是如果我使用new
选项,则可以将其作为wg
发送< / p>
两个示例之间有什么区别?以上2个中的哪一个是正确的?在某些情况下,一个优先于另一个吗?
我正在编写一个可以创建多个sync.WaitGroup
的程序,那么使用new
还是var
是否重要?
答案 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?