【发布时间】:2014-09-18 17:48:35
【问题描述】:
考虑以下 Go 代码(也在 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)
}
此代码产生以下输出:
s: foo
x: foo
s: bar
x: bar
s: bar
x: foo
s: bar
x: bar
假设这不是一些奇怪的编译器错误,我很好奇为什么 a) s 的值在 goroutine 版本中的解释与常规 func 调用和 b) 的解释不同,以及为什么将它分配给内部的局部变量循环在这两种情况下都有效。
【问题讨论】:
-
我挖掘@Mitchell 的
go func(s string) { ... }(s)成语。提出问题的另一种方式是,Go 范围规则意味着 both 中的funcs 您的示例正在访问它们运行时s的当前值; goroutine 只是在不同的时间运行。 -
使用竞态检测器运行此代码应该会发现问题。