dongyou4411 2018-12-15 10:48
浏览 129
已采纳

多个sync.WaitGroup的用法

I have seen a few different examples of sync.WaitGroup

Example 1

var wg sync.WaitGroup

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

Example 2

wg := new(sync.WaitGroup)

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

the difference is really in the way sync.WaitGroup is initialized var vs new

if using the var option it has to be passed as a pointer &wg to the goroutine but if I use the new option I can send it as wg

What is the difference between the two examples? Which of these 2 above is correct? Is one preferred over the other in certain situations?

I am writing a program which creates multiple sync.WaitGroups so does it matter if new or var is used?

  • 写回答

1条回答 默认 最新

  • 普通网友 2018-12-15 11:39
    关注

    Both of your examples work properly. Also note that instead of new(), you could also use a composite literal and take its address like this:

    var wg = &sync.WaitGroup{}
    

    Methods of sync.WaitGroup have pointer receiver, so whenever you call its methods, the address of the WaitGroup struct value is needed. This is not a problem, as when wg is a non-pointer, the wg.Add(1) and wg.Done() calls are shorthand for (&wg).Add(1) and (&wg).Done(), so the compiler automatically "rewrites" those calls to take the address of wg first, and use that address as the receiver of the methods.

    However, I still think that if a value is only useful as a pointer (sync.WaitGroup is a shining example), you should declare it and work with it as a pointer in the first place, so that leaves less room for errors.

    For example, if you use a non-pointer and you declare the function to expect a non-pointer, and you pass it as a non-pointer, you will get no compile-time error, yet it will misbehave (sync.WaitGroup should not be copied).

    Although today's linter would give you a warning message, still, I believe it's best to work with pointers all the time.

    Another reason to work with pointers: if a function would return a sync.WaitGroup, or if you have a map that stores sync.WaitGroup as values, you would not be able to call methods on the result, because return values of functions and map index operations are not addressable. If the function would return a pointer value, or if you would store pointers in the map in the first place, you could still call the methods without having to store them in a local variable. For details, see How can I store reference to the result of an operation in Go?

    For example:

    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
    

    But these work:

    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
    

    Read more about this here: Why should constructor of Go return address?

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 matlab求解平差
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料
  • ¥15 使用R语言marginaleffects包进行边际效应图绘制
  • ¥20 usb设备兼容性问题
  • ¥15 错误(10048): “调用exui内部功能”库命令的参数“参数4”不能接受空数据。怎么解决啊
  • ¥15 安装svn网络有问题怎么办