在goroutine中将函数作为参数传递

iszxjhcz  于 2023-09-28  发布在  Go
关注(0)|答案(1)|浏览(92)
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作为值传递,因此output应该为1。有时候会有两个人,有人能解释一下为什么吗?

2guxujil

2guxujil1#

go WithRecover(func() { printRewardAmount(rewardAmount) })

在上面的代码中,您只是将rewardAmount的值传递给printRewardAmount()函数,而不是传递给go例程。因此,rewardAmount的作用域仍然在go例程之外(在main()内部)。因此,根据go例程的执行顺序,输出可以是1或2。
只需将main()替换为以下内容即可查看rewardAmount的地址

func main() {
    var rewardAmount int
    rewardAmount = 1
    fmt.Println("address of rewardAmount in main:", &rewardAmount)
    go WithRecover(func() {
        fmt.Println("address of rewardAmount inside go routine:", &rewardAmount)
        printRewardAmount(rewardAmount)
    })
    if true {
        rewardAmount = 2
    }
    time.Sleep(100 * time.Millisecond)
}

full code in playground
但是当您执行以下操作时,实际上是将rewardAmount的值复制并传递给go例程。因此,输出将始终为1。

func main() {
    var rewardAmount int
    rewardAmount = 1
    fmt.Println("address of rewardAmount in main:", &rewardAmount)
    go func(rewardAmount int) {
        fmt.Println("address of rewardAmount inside go routine:", &rewardAmount)
        WithRecover(func() {
            printRewardAmount(rewardAmount)
        })
    }(rewardAmount)
    if true {
        rewardAmount = 2
    }
    time.Sleep(100 * time.Millisecond)
}

full code in playground

相关问题