import (
"fmt"
"time"
)
func WithRecover(r func()) {
r()
}
func printRewardAmount(rewardAmount int) {
fmt.Println(rewardAmount)
}
func main() {
var rewardAmount int
rewardAmount = 1
go WithRecover(func() { printRewardAmount(rewardAmount) })
if true {
rewardAmount = 2
}
time.Sleep(100 * time.Millisecond)
}
当我们将rewardAmount作为值传递时,输出应该是1。但有时我会得到2,有人能解释一下为什么吗?
在 Golang 中,当您将变量作为参数传递给 goroutine 时,您将在创建 goroutine 时捕获该变量的值,而不是在执行它时。这意味着 goroutine 捕获
rewardAmount
的当前值,该值可能是 1 或 2,具体取决于 goroutine 执行的时间。
在您的代码中,您有一个运行
WithRecover
的 goroutine,它又调用 printRewardAmount(rewardAmount)
。在创建 Goroutine 之后但在调用 rewardAmount
之前,main
变量在 time.Sleep
函数中被修改。如果 goroutine 在修改 rewardAmount
之前执行,它将捕获值 1,并且您将看到 1 作为输出。但是,如果 rewardAmount
的修改发生在 goroutine 执行之前,它将捕获值 2,并且您将看到 2 作为输出。
goroutine 的执行顺序无法保证,取决于 Go 调度器。这就是为什么您在不同时间观察到不同输出的原因。如果你想确保 goroutine 将
rewardAmount
的值捕获为 1,你可以将其作为参数传递给 goroutine:
go WithRecover(func(rewardAmount int) { printRewardAmount(rewardAmount) }, rewardAmount)
这样,您可以显式地将
rewardAmount
的当前值作为参数传递给 goroutine,确保它捕获正确的值。