通过迭代函数切片调用每个函数

way*_*are 2 go slice goroutine

我试图循环一片函数,然后调用其中的每个函数.但是我得到了奇怪的结果.这是我的代码:

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()
}
Run Code Online (Sandbox Code Playgroud)

我以为它会调用函数A,B然后调用C但是我的输出只得到Cs.

C
C
C
Run Code Online (Sandbox Code Playgroud)

请提出错误及其背后的逻辑.我怎样才能获得理想的行为.

去游乐场

k1m*_*90r 5

经典去骗局:)

官方围棋常见问题

for a, _ := range f {
    wg.Add(1)
    a:=a // this will make it work
    go func() {
        defer wg.Done()
        f[a]()
    }()
}
Run Code Online (Sandbox Code Playgroud)

func() {}()是一个关闭的关闭a.并且a是所有go funcgo例程的共享,因为for循环重用相同的var(在内存中意味着相同的地址,因此相同的值),所以自然它们都看到了最后的值a.

解决方案要么a:=a在关闭之前重新声明(如上所述).这将创建新的var(内存中的新地址),然后每次调用都是新的go func.

或者将其作为参数传递给go函数,在这种情况下,您传递a类似值的副本:

go func(i int) {
    defer wg.Done()
    f[i]()
}(a)
Run Code Online (Sandbox Code Playgroud)

你甚至不需要去试用这个https://play.golang.org/p/nkP9YfeOWF,例如演示相同的问题.这里的关键是"关闭".