我正在尝试循环一段函数,然后调用其中的每个函数。但是我得到了奇怪的结果。这是我的代码:
package main
import (
"fmt"
"sync"
)
func A() {
fmt.Println("A")
}
func B() {
fmt.Println("B")
}
func C() {
fmt.Println("C")
}
func main() {
type fs func()
var wg sync.WaitGroup
f := []fs{A, B, C}
for a, _ := range f {
wg.Add(1)
go func() {
defer wg.Done()
f[a]()
}()
}
wg.Wait()
}
我原以为它会调用函数 A、B,然后调用 C,但我的输出只得到 Cs。
C
C
C
请指出问题所在及其背后的逻辑。另外我怎样才能得到想要的行为。
最佳答案
经典的陷阱:)
官网FAQ
for a, _ := range f {
wg.Add(1)
a:=a // this will make it work
go func() {
defer wg.Done()
f[a]()
}()
}
您的 func() {}()
是一个关闭 a
的闭包。 a
是所有 go func
go 例程共享的,因为 for 循环重用相同的 var(意味着内存中的相同地址,因此具有相同的值),所以他们自然会看到a
的最后一个值。
解决方案是在关闭之前重新声明 a:=a
(如上)。这将创建新的 var(内存中的新地址),每次调用 go func
时都是新的。
或者将其作为参数传递给 go 函数,在这种情况下,您传递 a
值的副本,如下所示:
go func(i int) {
defer wg.Done()
f[i]()
}(a)
您甚至不需要在这个 https://play.golang.org/p/nkP9YfeOWF 中执行 go 例程例如演示相同的问题。这里的关键是“关闭”。
关于go - 通过迭代函数 slice 调用每个函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47467047/