为什么Golang在goroutine中处理不同的闭包? [英] Why does Golang handle closures differently in goroutines?
问题描述
请考虑以下Golang代码(也位于 Go Playground ):
Consider the following Golang 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\n", s)
fmt.Printf("x: %s\n", x)
}()
}
fmt.Println()
for _, s := range []string{"foo", "bar"} {
x := s
go func() {
fmt.Printf("s: %s\n", s)
fmt.Printf("x: %s\n", x)
}()
}
time.Sleep(time.Second)
}
此代码生成以下输出: / p>
This code produces the following output:
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中的Closures是词法作用域。这意味着来自外部作用域的闭包内引用的任何变量不是副本,而是实际上是引用。 A 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\n", s)
fmt.Printf("x: %s\n", x)
}(s)
}
这篇关于为什么Golang在goroutine中处理不同的闭包?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!