du27271 2017-11-24 05:47
浏览 36
已采纳

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

I am trying to loop a slice of function and then invoke every function in it. However I am getting strange results. Here is my code:

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()
}

I was thinking that it will invoke function A,B and then C but my output gets only Cs.

C
C
C

Please suggest whats wrong and the logic behind it. Also how can I get desired behavior.

Go Playground

  • 写回答

2条回答 默认 最新

  • dongmiao520892 2017-11-24 06:28
    关注

    Classic go gotcha :)

    Official Go FAQ

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

    Your func() {}() is a closure that closes over a. And a is a shared across all the go func go routines because for loop reuses the same var (meaning same address in memory, hence same value), so naturally they all see last value of a.

    Solution is either re-declare a:=a before closure (like above). This will create new var (new address in memory) which is then new for each invocation of go func.

    Or pass it in as parameter to the go function, in which case you pass a copy of value of a like so:

    go func(i int) {
        defer wg.Done()
        f[i]()
    }(a)
    

    You don't even need to have go routines this https://play.golang.org/p/nkP9YfeOWF for example demonstrates the same gotcha. The key here is 'closure'.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥50 h5唤醒支付宝并跳转至向小荷包转账界面
  • ¥15 算法题:数的划分,用记忆化DFS做WA求调
  • ¥15 chatglm-6b应用到django项目中,模型加载失败
  • ¥15 CreateBitmapFromWicBitmap内存释放问题。
  • ¥30 win c++ socket
  • ¥15 C# datagridview 栏位进度
  • ¥15 vue3页面el-table页面数据过多
  • ¥100 vue3中融入gRPC-web
  • ¥15 kali环境运行volatility分析android内存文件,缺profile
  • ¥15 写uniapp时遇到的问题