Methods 方法接收器是否作为指针的区别

Methods 方法接收器是否作为指针的区别,methods,go,Methods,Go,为什么我不把PrintValue定义为一个指针接收器*一个可以打印hello的接收器 package main import "fmt" type One struct{ a string } func (o *One)AssignValue(){ o.a = "hello" } func (o One)PrintValue(){ fmt.Println(o.a) } func main() { one := One{} one.AssignValu

为什么我不把PrintValue定义为一个指针接收器*一个可以打印hello的接收器

package main
import "fmt"


type One struct{
    a string
}
func (o *One)AssignValue(){
    o.a = "hello"
}
func (o One)PrintValue(){
    fmt.Println(o.a)
}

func main() {
    one := One{}
    one.AssignValue()
    one.PrintValue()
}
因为一个已经是第一类了。实例化语法

t := One{}
创建类型为1的值,而窗体

p := &One{}
创建指向类型为1的值的指针

这意味着调用t.PrintValue时不需要执行任何操作,因为接收方类型One已经与t类型One相同

调用p.PrintValue时,编译器会自动将可寻址变量转换为其指针形式,因为接收方类型1不等于p*1的类型。那么这个表达呢

p.PrintValue()
t.AssignValue()
转换为

(*p).PrintValue()
(&t).AssignValue()
调用t.AssignValue时还需要进行转换,因为此方法具有指针接收器,但我们提供了一个值。在可能的情况下,这也由编译器自动完成

发件人:

如果x类型的方法集包含m,并且参数列表可以分配给m的参数列表,则方法调用x.m有效。如果x是可寻址的,并且&x的方法集包含m,则x.m是&x.m的简写

这意味着

p.PrintValue()
t.AssignValue()
转换为

(*p).PrintValue()
(&t).AssignValue()
请注意,这并不总是可能的。例如,从函数返回值时:

func NewOne(s string) One { return One{s} }

NewOne("foo").AssignValue() // Not possible

x := NewOne("foo")
x.AssignValue() // Possible, automatically converted

这就是幕后的魔法。。。如果你问我的话,会有点困惑。但是,如果AssignValue没有定义为指针接收器,那么PrintValue会打印一个空字符串。这是为什么呢?因为这样会复制赋值中的o,并且只对副本进行修改。好的,这很有帮助。我认为初学者的书和例子中没有充分强调这种行为。对于像我这样来自动态语言的人来说,一个坏习惯是尝试在Go中重新创建一个类Python,并期望它的行为相同。谢谢这个答案实际上是错误的:您不需要指针接收器,因为在您的例子中,PrintValue看到的o的副本的a字段设置为hello。有关接收器的更多信息,请阅读。