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

What different does the * (pointer symbol) makes in the following Go method?

我正在学习本教程:https://github.com/astaxie/build-web-application-with-golang/blob/master/en/02.5.md

我仍然不太理解指针,所以过去让我有点困惑:func (h *Human) SayHi()。我尝试删除 * 并且输出结果完全相同。为什么在这种情况下 * 是必要的?有人可以用下面的代码给我一个不同输出的例子吗?

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\n", 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()
}

它的不同之处在于,该方法将定义在指向 Human 结构的指针上,并且该结构中的所有方法随后将对指向的值进行操作。

如果您要松开 *,该方法将对您调用该方法的结构的副本进行操作,因此您对该方法中的结构所做的任何写入对于调用方法的代码。

由于方法体只执行一个fmt.Printf并打印一些值,所以方法是否定义在指针上并没有太大的区别。

在某些情况下,为了并发安全,您最好不要在指针上定义方法,因为这可能会导致同时访问和写入底层结构值。

使用指针接收器有两个原因:

  1. 首先,避免在每次方法调用时复制值,如果值类型是大型结构,效率会更高)。
  2. 其次,该方法可以修改其接收者指向的值。

因此在您的示例中,如果您再添加一种转储方法来更改 phone,如下所示:

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

调用此方法后phone不会改变,这就是*点发挥作用的原因。