Передача указателя внутри цикла с анонимными функциями go вызывает использование только последнего указателя элемента
Поэтому в следующем коде я передаю указатели на анонимные функции 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{} вместо указателя на элемент.
Мой вопрос:
- Это определенное поведение?
- Как я могу переписать это, чтобы принять указатели на мой элемент {}?
Детская площадка:
http://play.golang.org/p/tcRvforQE4
Изменить: форматирование вопроса
1 ответ
Что происходит, так это то, что цикл for помещает значение elements[i]
В то же самое element
переменная для каждой итерации, не создавая новую. Это означает, что &element
всегда один и тот же адрес (попробуйте распечатать его перед вызовом функции!)
Простым решением было бы просто передать ему указатель на фактический член среза:
for i := range elements {
go func(element *Element){
fmt.Println("PostStream: ", element.Name)
waiting <- true
}(&elements[i])
}