go - 通过迭代函数 slice 调用每个函数

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

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

C
C
C

请指出问题所在及其背后的逻辑。另外我怎样才能得到想要的行为。

Go Playground

最佳答案

经典的陷阱:)

官网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/

相关文章:

rest - 已被 CORS 策略 : Response to preflight request doesn’t pass access control check 阻止

syntax - 如何从 as_slice() 更改为 [] 语法?

python - 了解列表切片中的负步骤

c++ - 如何在 C++ 中从 vector 中获取一系列项目

go - 如何将多个并发请求分配给 aws lambda 函数?

go - 为什么这个程序中存在竞争条件?

regex - 使用正则表达式替换将文本添加到多行字符串的每一行的开头

go - 了解 Golang 内存管理与大片字符串

http - 调用堆栈上的错误处理-HTTP请求处理程序

go - 用goroutine调用函数与将函数代码包装在goroutine之间有区别吗?