英文:
What is the method set of `sync.WaitGroup`?
问题
我有下面这个简单的程序:
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
。
为什么/如何能够工作?
英文:
I have this simple program below
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()
}
Notice that I use var wg sync.WaitGroup
as a value, not a pointer. But the page for the sync package specifies that the Add
, Done
and Wait
function take a *sync.WaitGroup
.
Why/How does this work?
答案1
得分: 9
sync.WaitGroup
的method 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()
// 等等
实际上是(&wg).Add(1)
,(&wg).Done()
等的简写形式。
这在规范: 调用中有说明:
> 如果x
是可寻址的,并且&x
的方法集包含m
,那么x.m()
是(&x).m()
的简写形式。
因此,当你有一个可寻址的值(变量是可寻址的),你可以在非指针值上调用任何具有指针接收器的方法,编译器会自动取地址并将其用作接收器值。
参考相关问题:
英文:
The method set of sync.WaitGroup
is the empty method set:
wg := sync.WaitGroup{}
fmt.Println(reflect.TypeOf(wg).NumMethod())
Output (try it on the Go Playground):
0
This is because all the methods of sync.WaitGroup
have pointer receivers, so they are all part of the method set of the *sync.WaitGroup
type.
When you do:
var wg sync.WaitGroup
wg.Add(1)
wg.Done()
// etc.
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:
答案2
得分: 2
在你的情况下,你正在修改一个全局的wg
对象,如果你将它传递给一个函数,你必须使用指针,因为你需要修改对象本身。如果你按值传递,那么在函数内部你将修改它的副本,而不是对象本身。
英文:
In your case you are modifying a global wg
object, if you pass it to a function you have to use pointer because you need to modify the object itself. If you pass by value, inside your function you will be modifying a copy of it, not the object itself.
答案3
得分: 1
从文档中可以看到,WaitGroup用于等待一组goroutine完成。主goroutine调用Add方法设置要等待的goroutine数量。然后每个goroutine运行并在完成时调用Done方法。同时,可以使用Wait方法阻塞,直到所有goroutine都完成。
对于Add方法,它设置了要等待的goroutine数量。从你的代码中可以看出,你只有一个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()
,它用于告诉一个goroutine已经完成工作,并让add
减少1。你可以看到下面的代码,了解Done
方法的工作原理:
// Done decrements the WaitGroup counter.
func (wg *WaitGroup) Done() {
wg.Add(-1)
}
最后,Wait
方法用于阻塞goroutine,直到WaitGroup计数器为零。
还有一个问题:
为什么要使用WaitGroup?
从你的代码中可以看出,如果不使用WaitGroup,你将无法打印goroutine的结果。
总之,你可以在文档中阅读更多信息。
英文:
From the documentation WaitGroup :
> A WaitGroup waits for a collection of goroutines to finish. The main
> goroutine calls Add to set the number of goroutines to wait for. Then
> each of the goroutines runs and calls Done when finished. At the same
> time, Wait can be used to block until all goroutines have finished.
From your Question
> How does this work?
So for Add
method is set the number of goroutine your called. From your code you have only one :
func main() {
wg.Add(1)
go func() {
fmt.Println("starting...")
time.Sleep(1 * time.Second)
fmt.Println("done....")
wg.Done()
} ()
wg.Wait()
}
so it will tells goroutine to wait and print the result.
as for wg.Done()
this is for telling the one gouroutine has finished to work. and it tells to the add
to decrement to -1
. You can see the code below How Done
method works :
// Done decrements the WaitGroup counter.
func (wg *WaitGroup) Done() {
wg.Add(-1)
}
and finally for the Wait
method this is for blocking goroutine until the WaitGroup counter is zero.
And another:
> Why ?
from your code above if you don't use WaitGroup
you will not be able to print the result from the goroutine.
All in all you can read it in the documentation.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论