我在下面有这个简单的程序
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,Done和Wait函数采用*sync.WaitGroup.
为什么/这是如何工作的?
的设定方法的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
xis addressable and&x's method set containsm,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?