*(指针符号)在以下Go方法中有什么不同?

I'm following this tutorial: https://github.com/astaxie/build-web-application-with-golang/blob/master/en/02.5.md.

I still don't understand pointers very well so this past confuses me a bit: func (h *Human) SayHi(). I tried removing the * and the output turned out to be exactly the same. Why is the * necessary in this case? Could someone give me an example of a different output with the code below?

package main
import "fmt"

type Human struct {
    name string
    age int
    phone string
}

type Student struct {
    Human // anonymous field
    school string
}

type Employee struct {
    Human 
    company string
}

// define a method in Human
func (h *Human) SayHi() {
    fmt.Printf("Hi, I am %s you can call me on %s
", h.name, h.phone)
}

func main() {
    mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"}
    sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}

    mark.SayHi()
    sam.SayHi()
}

There are two reasons to use a pointer receiver:

  1. First, to avoid copying the value on each method call, more efficient if the value type is a large struct).
  2. Second, the method can modify the value that its receiver points to.

So in your example, if you add one more dump method to change phone like this:

func (h Human) ChangePhone() {
    h.phone = 'whatever'
}

The phone does not change after you call this method, that's why point * comes into play.

The difference it does make is that the method will be defined on a pointer to a Human struct and all the methods in the struct will subsequently operate on the value pointed to.

If you were to loose the *, the method would operate on a copy of the struct you call the method on, so any write you'd do to the struct in the method would be useless for the code calling the method.

Since the method body only executes a fmt.Printf and prints some values, it does not really make a big difference if the method is defined on the pointer or not.

There are some cases where in the interest of concurrent-safety, you'd better not define methods on pointers, since this may lead to simultaneous access and writing of the underlying struct values.