WaitGroups 参考中的指针或变量
在sync 包中,WaitGroups 的 Add、Done 和 Wait 函数都是由指向 WaitGroup 的指针。但是,以下代码似乎与此约定相矛盾:
package main import ( "fmt" "sync" "time" ) func worker(id int, wg *sync.WaitGroup) { defer wg.Done() fmt.Printf("Worker %d starting\n", id) time.Sleep(time.Second) fmt.Printf("Worker %d done\n", id) } func main() { var wg sync.WaitGroup for i := 1; i <= 5; i++ { wg.Add(1) go worker(i, &wg) } wg.Wait() }
在此代码中,虽然使用指针变量调用 Done,但使用变量(而不是指针)调用 Add 和 Wait。
解释:
尽管变量声明为 var wgsync.WaitGroup,但 Add, Done 和 Wait 函数通过其指针接收器 (*WaitGroup) 进行访问。 wg 的值被 Go 编译器隐式转换为指针。这是必要的,因为这些方法被定义为指针接收器,如函数声明中所示:
Add -------> func (wg *WaitGroup) Add(delta int) Done ------> func (wg *WaitGroup) Done() Wait ------> func (wg *WaitGroup) Wait()
当将非指针值传递给指针接收器方法时,编译器会自动获取其地址(指针到值)。因此,即使 wg 被声明为变量,所有三个函数仍然在指向 wg 的指针上调用。
使用指针接收器的主要原因是避免不必要的数据复制。通过传递指针,该函数可以直接修改底层的 WaitGroup,而不是复制它。这提高了性能,特别是对于频繁修改的 WaitGroups。
在提供的代码中,将 wg 的地址传递给工作人员至关重要,因为如果它作为值传递(不带 &),则中的 Done 函数每个工作线程都会引用与主函数中的 Add 和 Wait 不同的指针。这会导致不正确的行为。
以上是为什么即使声明为变量,也要使用指针调用 WaitGroup 的 Add、Done 和 Wait 函数?的详细内容。更多信息请关注PHP中文网其他相关文章!