我是 Go 的初学者,正在学习以这段代码为例的在线课程:func ConcurrentMutex(url string, fetcher Fetcher, f *fetchState) { var done sync.WaitGroup for _, u := range urls { done.Add(1) u2 := u go func() { defer done.Done() ConcurrentMutex(u2, fetcher, f) }() //go func(u string) { // defer done.Done() // ConcurrentMutex(u, fetcher, f) //}(u) } done.Wait() return}u 的类型是字符串,在我看来,我们应该能够将 u 传递给内部函数中的 ConcurrentMutex 调用,而无需将其值复制到 u2。然而,教授坚持认为,Go 内存模型意味着当我们不断改变 u 的值时,它会影响对 ConcurrentMutex 的不同调用。我仍然不完全确定为什么。调用函数时的 u 值不应该传递给函数吗?如果我们传递一个指针,我会理解的,但因为我们不是,这让我感到困惑。有人可以解释一下 Go 的内存模型是如何解释这个块的吗?注意:注释掉的内部函数是讲座视频中示例中使用的原始函数,但在讲座笔记中进行了更改。在我看来两者都是等价的,所以我想这个问题适用于两者。
1 回答
喵喵时光机
TA贡献1846条经验 获得超7个赞
您正在使用的是关闭。u2 在内部函数和围绕它的函数之间共享。这意味着随着 u2 的每次迭代被修改,修改后的值对内部函数可见。更好的编写方式是使用已注释掉的代码。通过显式地将值传递给 goroutine,您可以确保 goroutine 携带它自己的副本,该副本不会被周围的函数修改。
Go 规范对此有何评论:Go 规范
函数文字 函数文字表示匿名函数。
FunctionLit = "func" 签名 FunctionBody 。func(a, b int, z float64) bool { return a*b < int(z) } 函数字面量可以分配给变量或直接调用。
f := func(x, y int) int { return x + y } func(ch chan int) { ch <- ACK }(replyChan) 函数字面量是闭包:它们可以引用在周围函数中定义的变量。然后,这些变量在周围的函数和函数字面量之间共享,只要它们可以访问,它们就会继续存在。
希望这能回答你的问题。
- 1 回答
- 0 关注
- 113 浏览
添加回答
举报
0/150
提交
取消