我下面有这个简单的程序
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是值,而不是指针。但是sync包的页面指定Add,Done和Wait函数采用*sync.WaitGroup。
var wg sync.WaitGroup
Add
Done
Wait
*sync.WaitGroup
为什么/如何运作?
的设定方法的sync.WaitGroup是空的方法集:
sync.WaitGroup
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()等等。
(&wg).Add(1)
(&wg).Done()
这是在规范中:致电:
如果x是可寻址且&x方法集包含m,x.m()则为的简写(&x).m()。
x
&x
m
x.m()
(&x).m()
因此,当您拥有一个可寻址的值(变量是可寻址的)时,您可以调用在非指针值上具有指针接收器的任何方法,并且编译器将自动获取该地址并将其用作接收器值。