为什么 Go 在 goroutines 中处理闭包的方式不同? [英] Why does Go handle closures differently in goroutines?

查看:27
本文介绍了为什么 Go 在 goroutines 中处理闭包的方式不同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下 Go 代码(也在 Go Playground 上):

Consider the following Go code (also on the Go Playground):

package main

import "fmt"
import "time"

func main() {
    for _, s := range []string{"foo", "bar"} {
        x := s
        func() {
            fmt.Printf("s: %s
", s)
            fmt.Printf("x: %s
", x)
        }()
    }
    fmt.Println()
    for _, s := range []string{"foo", "bar"} {
        x := s
        go func() {
            fmt.Printf("s: %s
", s)
            fmt.Printf("x: %s
", x)
        }()
    }
    time.Sleep(time.Second)
}

此代码产生以下输出:

s: foo
x: foo
s: bar
x: bar

s: bar
x: foo
s: bar
x: bar

假设这不是一些奇怪的编译器错误,我很好奇为什么 a) s 的值在 goroutine 版本和常规 func 调用中的解释不同,以及 b) 为什么将它分配给内部的局部变量循环适用于两种情况.

Assuming this isn't some odd compiler bug, I'm curious why a) the value of s is interpreted differently in the goroutine version then in the regular func call and b) and why assigning it to a local variable inside the loop works in both cases.

推荐答案

Go 中的闭包是词法作用域的.这意味着从外部"作用域在闭包内引用的任何变量都不是副本,而是实际上是一个引用.for 循环实际上多次重用同一个变量,因此您在 s 变量的读/写之间引入了竞争条件.

Closures in Go are lexically scoped. This means that any variables referenced within the closure from the "outer" scope are not a copy but are in fact a reference. A for loop actually reuses the same variable multiple times, so you're introducing a race condition between the read/write of the s variable.

但是 x 正在分配一个新变量(使用 :=)并复制 s,这导致每次都是正确的结果时间.

But x is allocating a new variable (with the :=) and copying s, which results in that being the correct result every time.

一般来说,最好的做法是传入您想要的任何参数,这样您就没有引用了.示例:

In general, it is a best practice to pass in any arguments you want so that you don't have references. Example:

for _, s := range []string{"foo", "bar"} {
    x := s
    go func(s string) {
        fmt.Printf("s: %s
", s)
        fmt.Printf("x: %s
", x)
    }(s)
}

这篇关于为什么 Go 在 goroutines 中处理闭包的方式不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆