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

receiver's usage

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 
}

When I use function in golang, If I declare value variable, when I use function I made, I had to put only value variable on paramter. like,

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

despite I declared Person as a value struct in Student struct, as you see my code, receiver functions(greeting1, greeting2) are getting two type parameters which are *Person, and Person. I cannot understand that why greeting1 function is functioning without error, despite I put value variable as a parameter. Thank you for you guys help.

Simplifying your example code to focus on the question / issue at hand:

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()
}

Prints:

&{joe 41}
0xc00000c028

In short, the call p.greeting1() works because Go sees that Person (the type of p) has a greeting1 method defined on a pointer receiver. So it treats the call p.greeting1() as equivalent to (&p).greeting1(). As mkopriva said in a comment, this is clearly laid out in the Go spec:

A method call x.m() is valid if the method set of (the type of) x contains m and the argument list can be assigned to the parameter list of m. If x is addressable and &x's method set contains m, x.m() is shorthand for (&x).m()

This is done for convenience. Since pointer receivers are quite necessary and popular in Go - you need them whenever your method mutates the underlying object - it helps write cleaner code. You shouldn't be forced to write (&p).greeting1() where p.greeting1() would do - this substituion is unambiguous as the compiler knows what methods are defined on Person, and with which receivers.

Effective Go has a section on pointer vs. value receivers that you should read. Here's one relevant quote:

When the value is addressable, the language takes care of the common case of invoking a pointer method on a value by inserting the address operator automatically. In our example, the variable b is addressable, so we can call its Write method with just b.Write. The compiler will rewrite that to (&b).Write for us.

Actually Go is an object oriented language in its own way. It uses struct instead of classes. If you want to have a class, you must make a struct and relate some funcs to it by a pointer of that struct, So later you can create many independent object from your struct. You can use the function new which will return a pointer of your struct. Like:

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