`sync.WaitGroup` 的方法集是什么?

Jer*_*via 5 go

我在下面有这个简单的程序

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()

}
Run Code Online (Sandbox Code Playgroud)

请注意,我var wg sync.WaitGroup用作值,而不是指针。但是同步包页面指定Add,DoneWait函数采用*sync.WaitGroup.

为什么/这是如何工作的?

icz*_*cza 9

设定方法sync.WaitGroup是空的方法集:

wg := sync.WaitGroup{}
fmt.Println(reflect.TypeOf(wg).NumMethod())
Run Code Online (Sandbox Code Playgroud)

输出(在Go Playground上试试):

0
Run Code Online (Sandbox Code Playgroud)

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

当你这样做时:

var wg sync.WaitGroup

wg.Add(1)
wg.Done()
// etc.
Run Code Online (Sandbox Code Playgroud)

This is actually a shorthand for (&wg).Add(1), (&wg).Done() etc.

This is in Spec: Calls:

If x is addressable and &x's method set contains m, x.m() is shorthand for (&x).m().

So when you have a value that is addressable (a variable is addressable), you may call any methods that have pointer receiver on non-pointer values, and the compiler will automatically take the address and use that as the receiver value.

See related question:

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