我有些存放Individual
物品中分得一杯羹。 其追加到片之前,我打印的名字Individual
对象。
之后,我已经将其存储在切片,然后我找回它作为一个指针,并希望将名称更改为"Peter"
,但由于它的变化不工作仍版画"Steve"
。 为什么?
type Individual interface {
GetName() *string
SetName(name string)
}
type Person struct {
name string
}
// Implement functions of the Individual interface
func (p Person) GetName() *string {
return &p.name
}
func (p Person) SetName(newName string) {
name := p.GetName();
*name = newName
}
var individuals []Individual
func main() {
person := Person{name: "Steve"}
fmt.Println(person)
individuals = append(individuals, person) // append Person to slice
p1 := individuals[0] // Retrieve the only Person from slice
p1.SetName("Peter") // Change name
fmt.Println(p1) // Should print "Peter", but prints "Steve"
fmt.Println(person) // Should print "Peter", but prints "Steve"
}
每当一个方法想要修改接收器, 它必须是一个指针值 ; 该方法必须有一个指针接收器。
如果一个方法具有非指针接收器,副本将被制成,当调用该方法通过。 从这一点来说,无论你与接收器做什么,你只能修改副本,而不是原来的。
因此,在你的例子:
func (p Person) SetName(newName string) {
name := p.GetName();
*name = newName
}
当SetName()
被调用时,副本作出的Person
。 里面SetName()
你获得的地址name
副本的领域,你修改。 (实际上, 复制副本 ,以后会更多......)
解决方案:使用指针接收器:
func (p *Person) SetName(newName string) {
name := p.GetName();
*name = newName
}
从这点上,只有*Person
实现了Individual
,所以使用的时候附加一个指针:
individuals = append(individuals, &person)
这是棘手的,因为在此之后它门槛将无法正常工作。 这是为什么?
这是因为Person.GetName()
仍具有非指针接收器:
func (p Person) GetName() *string {
return &p.name
}
所以,当GetName()
是由被称为SetName()
副本将被再次提出,和GetName()
将返回的地址name
副本的领域, SetName()
仅修改调用创建副本GetName()
。
因此,为了使所有的工作,你也可以选择使用指针接收器GetName()
func (p *Person) GetName() *string {
return &p.name
}
现在,它的工作,输出(尝试在转到操场 ):
{Steve}
&{Peter}
{Peter}
但要知道,最简单,最推荐的方法很简单:
func (p *Person) SetName(newName string) {
p.name = newName
}
这一切都需要。
两件事情来解决这个问题:
- 你需要的方法通过“指针”的方法连接,否则名称只在方法内改变。
- 您需要使用指针实际的
Person
的变量,因为它们需要实现一个接口
type Individual interface {
GetName() *string
SetName(name string)
}
type Person struct {
name string
}
// Implement functions of the Individual interface
func (p Person) GetName() *string {
return &p.name
}
func (p *Person) SetName(newName string) {
p.name = newName
}
var individuals []Individual
func main() {
person := &Person{name: "Steve"}
fmt.Println(person)
individuals = append(individuals, person) // append Person to slice
p1 := individuals[0] // Retrieve the only Person from slice
p1.SetName("Peter") // Change name
fmt.Println(p1) // Prints "Steve"
fmt.Println(person) // Prints "Steve"
}
例如在去游乐场 。
见https://play.golang.org/p/eg8oYDV6Xx p1和p2都已经解决了,你不需要他们的地址(地址的地址),只需打印p1和p2 -他们将是一样的,你可以看到。