使用匿名go函数在循环内传递指针会导致仅使用最后一个元素指针

时间:2014-05-13 16:44:24

标签: pointers go goroutine

因此,在下面的代码中,我将指向匿名go函数的指针传递给了函数,但代码的行为并不像我期望的那样。

package main

import "fmt"

type (
    Element struct{
        Name string
    }
)

func main() {
    elements := []Element{{"first"}, {"second"}, {"third"}, {"fourth"}}
    waiting := make(chan bool)

    for _, element := range elements {
        go func(element *Element){
            fmt.Println("Element Name: ", element.Name)
            waiting <- true
        }(&element)
    }

    for i := 0; i < 4; i++{
        <- waiting
    }
}

我希望代码写一下:

  • '第一'
  • '第二'
  • '第三'
  • '第四'

以任何顺序,而是打印:

  • '第四'
  • '第四'
  • '第四'
  • '第四'

所以看起来匿名go函数'解析'它的* Element参数到当时那个循环中的任何东西,所以这个代码将通过传递Element {}本身而不是指向元素的指针来修复。 / p>

我的问题是:

  • 这是定义的行为吗?
  • 我怎么能重写这个接受 指向我的元素的指针{}?

游乐场:

http://play.golang.org/p/tcRvforQE4

编辑:问题格式

1 个答案:

答案 0 :(得分:7)

对于每次迭代,for循环将elements[i]的值放在相同的element变量中,而不是创建新的迭代。这意味着&element始终是相同的地址(在调用函数之前尝试打印它!)

一个简单的解决方案是将指针传递给切片的实际成员:

for i := range elements {

    go func(element *Element){
        fmt.Println("PostStream: ", element.Name)
        waiting <- true
    }(&elements[i])
}