为了账号安全,请及时绑定邮箱和手机立即绑定

为什么我们需要在这里复制 u 的值?

为什么我们需要在这里复制 u 的值?

Go
莫回无 2022-06-01 10:06:53
我是 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) 函数字面量是闭包:它们可以引用在周围函数中定义的变量。然后,这些变量在周围的函数和函数字面量之间共享,只要它们可以访问,它们就会继续存在。

希望这能回答你的问题。


查看完整回答
反对 回复 2022-06-01
  • 1 回答
  • 0 关注
  • 113 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信