pointers - 多个 sync.WaitGroup 使用
问题描述
我见过几个不同的例子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
这两个例子有什么区别?以上2个哪个是正确的?在某些情况下,一个优先于另一个吗?
我正在编写一个创建多个sync.WaitGroup
s 的程序,所以是否使用new
或var
使用它是否重要?
解决方案
您的两个示例都可以正常工作。另请注意new()
,您还可以使用复合文字代替 ,并像这样获取其地址:
var wg = &sync.WaitGroup{}
方法sync.WaitGroup
具有指针接收器,因此无论何时调用其方法,WaitGroup
都需要结构值的地址。这不是问题,因为 whenwg
是非指针,wg.Add(1)
and调用是andwg.Done()
的简写,因此编译器会自动“重写”这些调用以获取first 的地址,并将该地址用作方法的接收者。(&wg).Add(1)
(&wg).Done()
wg
但是,我仍然认为,如果一个值仅用作指针(sync.WaitGroup
这是一个光辉的例子),您应该首先声明它并将其作为指针使用,这样就可以减少出错的空间。
例如,如果你使用一个非指针并且你声明函数期望一个非指针,并且你将它作为一个非指针传递,你不会得到编译时错误,但它会行为不端(sync.WaitGroup
不应该被复制)。
虽然今天的 linter 会给你一个警告信息,但我相信最好始终使用指针。
使用指针的另一个原因:如果函数将返回 a sync.WaitGroup
,或者如果您有一个存储sync.WaitGroup
为值的映射,您将无法对结果调用方法,因为函数的返回值和映射索引操作是不可寻址的。如果函数将返回一个指针值,或者如果您首先将指针存储在映射中,您仍然可以调用这些方法,而不必将它们存储在局部变量中。有关详细信息,请参阅如何在 Go 中存储对操作结果的引用?
例如:
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
但这些工作:
func getWg() *sync.WaitGroup { return &sync.WaitGroup{} }
getWg().Wait() // Works, you can call methods on the return value
m := map[int]*sync.WaitGroup{
1: &sync.WaitGroup{},
}
m[1].Wait() // Also works
在此处阅读有关此内容的更多信息:Go 的构造函数为什么要返回地址?
推荐阅读
- hibernate - 在 Quarkus 中添加 Hibernate ORM Panache 时在测试中发生异常
- javascript - 设置动画持续时间的时刻
- unity3d - 统一为游戏视图添加分辨率
- spagobi - 运行新的 spagobi 应用程序 SBIErrorPage.title 时出错
- acumatica - Acumatica 中的 Muslti Select 控件未显示强制 (*) 符号
- c# - 我在使用 OWIN 的 asp.net webforms 应用程序中的 ADFS SSO 中出现错误
- regex - 谁能帮助我理解下面的 groovy 脚本
- google-cloud-platform - 如何让 podman/buildah 容器在 GCE 上的 CentOS 下运行?
- visual-studio-code - 覆盖 Visual Studio Code 扩展视图容器图标以可视化扩展功能的一些变化
- laravel - 如何使用索引方法在 Laravel 中显示资源列表