【问题标题】:What is the method set of `sync.WaitGroup`?`sync.WaitGroup` 的方法集是什么?
【发布时间】:2017-07-17 14:32:38
【问题描述】:

我下面有这个简单的程序

package main

import (
    "fmt"
    "sync"
    "time"
)

var wg sync.WaitGroup

func main() {
    wg.Add(1)

    go func() {
        fmt.Println("starting...")
        time.Sleep(1 * time.Second)
        fmt.Println("done....")
        wg.Done()
    } ()

    wg.Wait()

}

请注意,我使用var wg sync.WaitGroup 作为值,而不是指针。但是page for the sync package 指定AddDoneWait 函数采用*sync.WaitGroup

为什么/如何工作?

【问题讨论】:

  • 你是对的..
  • 我刚刚意识到我没有正确阅读您的问题。

标签: go


【解决方案1】:

sync.WaitGroupmethod set 是空方法集:

wg := sync.WaitGroup{}
fmt.Println(reflect.TypeOf(wg).NumMethod())

输出(在Go Playground上试试):

0

这是因为sync.WaitGroup的所有方法都有指针接收器,所以它们都是*sync.WaitGroup类型的方法集的一部分。

当你这样做时:

var wg sync.WaitGroup

wg.Add(1)
wg.Done()
// etc.

这实际上是(&wg).Add(1)(&wg).Done()等的简写。

这是Spec: Calls:

如果x 是可寻址的并且&x 的方法集包含m,则x.m()(&x).m() 的简写。

因此,当您有一个可寻址的值(变量是可寻址的)时,您可以调用任何在非指针值上具有指针接收器的方法,编译器将自动获取该地址并将其用作接收器值。

查看相关问题:

Calling a method with a pointer receiver by an object instead of a pointer to it?

【讨论】:

    【解决方案2】:

    来自文档WaitGroup

    WaitGroup 等待一组 goroutine 完成。主要的 goroutine 调用 Add 来设置要等待的 goroutine 的数量。然后 每个 goroutine 运行并在完成时调用 Done。同时 时间,Wait 可以用来阻塞,直到所有的 goroutine 都完成。

    来自您的问题

    这是如何工作的?

    所以对于Add 方法是设置你调用的goroutine 的数量。从您的代码中,您只有一个:

    func main() {
        wg.Add(1)
    
        go func() {
            fmt.Println("starting...")
            time.Sleep(1 * time.Second)
            fmt.Println("done....")
            wg.Done()
        } ()
    
        wg.Wait()
    
    }
    

    所以它会告诉 goroutine 等待并打印结果。 至于wg.Done(),这是为了告诉一个gouroutine已经完成了工作。它告诉add 递减到-1。您可以在下面查看代码 Done 方法的工作原理:

    // Done decrements the WaitGroup counter.
    func (wg *WaitGroup) Done() {
        wg.Add(-1)
    }
    

    最后对于 Wait 方法,这是用于阻塞 goroutine 直到 WaitGroup 计数器为零。

    还有一个:

    为什么?

    如果您不使用WaitGroup,您将无法从上面的代码中打印 goroutine 的结果。

    总而言之,您可以在文档中阅读它。

    【讨论】:

      【解决方案3】:

      在您的情况下,您正在修改全局 wg 对象,如果将其传递给函数,则必须使用指针,因为您需要修改对象本身。如果您按值传递,则在您的函数内部您将修改它的副本,而不是对象本身。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-07-03
        • 2019-02-12
        • 1970-01-01
        • 2019-02-10
        • 2020-08-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多