接收器在struct中使用struct的问题

时间:2019-01-20 10:31:05

标签: go receiver

接收者的用法

package main

import "fmt"

type Person struct {
    name string
    age  int
}

func (p *Person) greeting1() {

    fmt.Println(p)  //&{0}
    fmt.Println(&p) //0xc000086018
    fmt.Println("Hello~")
}

func (p Person) greeting2() {
    fmt.Println(p)  //{0}
    fmt.Println(&p) //&{0}
    fmt.Println("Hello~")
}

type Student struct {
    //p Persion -> has a 
    Person // -> is a 
    school string
    grade  int
}

func test1(p Student) {
    fmt.Println(p)
}

func test2(p *Student){
    fmt.Println(p)
}

func main() {
    var s Student
    //s.p.greeting()
    s.greeting1()
    s.greeting2()

    test1(s)
    //test2(s) -> error 
}

当我在golang中使用函数时,如果我声明了值变量,那么当我使用自己制作的函数时,我只需要将值变量放在参数上。喜欢,

a int= 10;
func func1(param int){
 fmt.Println(fmt)
}

尽管我在“学生”结构中将“人”声明为值结构, 如您所见,我的代码 接收器函数(greeting1,greeting2)正在获取两个类型参数,分别是* Person和Person。 尽管我将value变量作为参数,但我无法理解为什么greeting1函数正常运行。 谢谢大家的帮助。

2 个答案:

答案 0 :(得分:1)

简化示例代码,重点关注当前的问题:

package main

import "fmt"

type Person struct {
    name string
    age  int
}

func (p *Person) greeting1() {
    fmt.Println(p)
    fmt.Println(&p)
}

func main() {
    var p Person
    p.name = "joe"
    p.age = 41
    p.greeting1()
}

打印:

&{joe 41}
0xc00000c028

简而言之,调用p.greeting1()之所以有效,是因为Go看到Personp的类型)在指针接收器上定义了一个greeting1方法。因此,它将呼叫p.greeting1()等同于(&p).greeting1()。正如mkopriva在评论中所说,这在Go spec中明确列出:

  

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

的简写

这样做是为了方便。由于指针接收器在Go中非常必要且很流行-当方法改变基础对象时,您就需要它们-它有助于编写更简洁的代码。您不应被迫在(&p).greeting1()会写的地方写p.greeting1()-这种替换是明确的,因为编译器知道Person上定义了哪些方法,以及接收者。

Effective Go在pointer vs. value receivers上有一个部分,您应阅读。这是一个相关的报价:

  

当值是可寻址的时,该语言将照顾通用   通过插入地址在值上调用指针方法的情况   自动操作。在我们的示例中,变量b是可寻址的,   因此我们可以仅使用b.Write调用其Write方法。编译器将   将其重写为(&b)。为我们写信。

答案 1 :(得分:0)

实际上Go本身就是一种面向对象的语言。它使用结构而不是类。如果您想拥有一个类,则必须创建一个结构,并通过该结构的指针将一些函数与该函数相关联,以便稍后可以从该结构中创建许多独立的对象。您可以使用new函数,该函数将返回结构的指针。喜欢:

p:=new(person)
p.name = "joe"
p.age = 41
p.greeting1()