带有指针值的 Go 通道在 for 循环中的行为不符合预期[重复]
Posted
技术标签:
【中文标题】带有指针值的 Go 通道在 for 循环中的行为不符合预期[重复]【英文标题】:Go channel with pointer value doesn't behave as expected in for loop [duplicate] 【发布时间】:2021-12-07 13:12:54 【问题描述】:我有一个问题,当从切片中对源进行测距时,我的通道中的数据在下游接收器中发生了更改,我不确定为什么会出现这种情况: https://play.golang.org/p/fPZJRj6XTRO
import (
"fmt"
)
func main()
fmt.Println("Hello, playground")
chanA := make(chan *string)
go func()
data := []string
"A",
"B",
"C",
for _, d := range data
chanA <- &d
close(chanA)
()
for res := range chanA
fmt.Println(*res)
结果:
Hello, playground
B
B
C
预期:
Hello, playground
A
B
C
【问题讨论】:
golang.org/doc/faq#closures_and_goroutines 除非有令人信服的理由,否则不要在频道上发送指针。通道写入将是 goroutine 安全的,但对该指针的并发写入则不会。 @colm.anseo 谢谢,我知道:D 【参考方案1】:您正在获取循环变量d
的地址。虽然地址保持不变,但循环变量的值在迭代之间会发生变化。当主程序取消引用指针时,它将获得循环变量的(有些随机的)当前值。要解决此问题,请在循环内复制变量:
for _, d := range data
d := d
chanA <- str1stringA: &d
:=
为循环的每次迭代创建一个新变量。
完整代码在这里:https://play.golang.org/p/kCD140I04_r
【讨论】:
这有帮助,谢谢,但从技术上讲,变量的地址不在迭代之间改变会更准确吗? @EatonEmmerich 哦,是的,你当然是对的。我将添加更多文字以明确更改的是值而不是地址。【参考方案2】:变量 d 不会在每次迭代中重新声明,因此它需要一个新变量作为 for 循环中内容的副本,即:
for _, d := range data
d2 := d
chanA <- &d2
【讨论】:
以上是关于带有指针值的 Go 通道在 for 循环中的行为不符合预期[重复]的主要内容,如果未能解决你的问题,请参考以下文章