最后一个索引总是覆盖一块struct值

问题描述 投票:0回答:1

我无法理解此代码块的行为。我做错了什么,应该采取什么样的正确方法呢?

import (
    "fmt"
    "strconv"
)

type Record struct {
    name *string
}
type person struct {
    name string
}

func main() {
    var Records []*Record
    var persons []person
    for i := 0; i < 10; i++ {
        newValue := person{name: strconv.Itoa(i)}
        persons = append(persons, newValue)
    }
    for _, personone := range persons {
        newRecord := &Record{}
        getName(newRecord, &personone)
        Records = append(Records, newRecord)
    }
    for _, record := range Records {
        fmt.Println(*record.name)
    }

}

func getName(record *Record, value *person) {
    record.name = &value.name
}

我希望这段代码打印0到9,但它总是打印9,最后一个值。

go
1个回答
2
投票

for _, personone := range persons {

在这个语句中,personone是一个声明一次的变量,并在每次迭代时被覆盖。

然后你在这个声明getName(newRecord, &personone)中获得它的地址。

因此,每次都传递相同的地址,每次迭代都会更改。

因此,您最终拥有相同的值,因为您已分配了相同的地址。

如何修复:如果你实际上不需要它们,请不要使用指针。

一个超级肮脏的黑客将明确地制作结构的副本https://play.golang.org/p/Sp4xD88rfvE

for _, personone := range persons {
    personone := personone // <-- see here
    newRecord := &Record{}
    getName(newRecord, &personone)
    Records = append(Records, newRecord)
}

但我真的不建议你这样做

© www.soinside.com 2019 - 2024. All rights reserved.