gpt4 book ai didi

pointers - 要在 for 循环中使用 goroutine,为什么迭代指向结构的指针而不是结构本身有效

转载 作者:IT王子 更新时间:2023-10-29 02:08:09 25 4
gpt4 key购买 nike

背景

我正在阅读 Go 中的 50 种色调,特别是 Iteration Variables and Closures in "for" Statements ,我将从中摘录。

不正确

    package main

import (
"fmt"
"time"
)

type field struct {
name string
}

func (p *field) print() {
fmt.Println(p.name)
}

func main() {
data := []field{{"one"},{"two"},{"three"}}

for _,v := range data {
go v.print()
}

time.Sleep(3 * time.Second)
//goroutines print: three, three, three
}

正确

[]field{{"one"},{"two"},{"three"}} 更改为 []*field{{"one"},{"two"}、{"three"}}onetwothree 将按某种顺序打印。

我的思考过程

  1. 在不正确的地方,go v.print() 被编译器替换为 go (&v).print() 因为 print( ) 在指针接收器上定义。

  2. 直到生成的 goroutine 被执行,运行时只知道 goroutine 应该执行 print(),但不知道应该传递哪个实例的指针作为接收者。

  3. 当派生的 goroutine 被执行时,for 循环很可能已经终止,所以当我们想决定应该将哪个值作为接收者传递时,我们得到 v 的地址>,在整个循环中共享,在每次迭代中更新,所以我们将data的最后一个元素的地址作为接收者传递给print(),即为什么我们打印 3 three

问题

对我来说,将 []field 更改为 []*field 只会让编译器跳过第 1 步,但不会更改第 2 步和第 3 步,所以我不不知道为什么这样可以解决问题。

我想我的思维过程肯定存在一些缺陷,非常感谢您的建议。

更新

我碰巧看到另一个正确的实现here ,我想我可能知道我的思维过程哪里出了问题。

data := []field{{"one"}, {"two"}, {"three"}}

for i := range data {
go data[i].print()
}

问题是,要作为接收者传递给 print() 的指针是在第 2 步而不是第 3 步中确定的。这意味着在不正确的版本中,我们传递的是相同的地址在每次迭代中,但它指向的内容 (data) 在每次迭代中更新。然而,在正确的版本中,作为接收者传递给 print() 的指针指向 field 的实际元素。这同样适用于使用索引的情况。

最佳答案

你的接收器是一个指针,你必须将你的字段 slice 定义为指针,这就是这段代码有效的原因

data := []*field{{"one"}, {"two"}, {"three"}}

如果您将接收器更改为非指针,您的代码也可以正常工作。

func (p field) print() {
fmt.Println(p.name)
}

data := []field{{"one"}, {"two"}, {"three"}}

关于pointers - 要在 for 循环中使用 goroutine,为什么迭代指向结构的指针而不是结构本身有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53737075/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com